translate.c 352.8 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 21 22 23 24 25
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

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

P
pbrook 已提交
32 33 34 35
#include "helper.h"
#define GEN_HELPER 1
#include "helper.h"

36 37 38 39
#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2
#define GDBSTUB_SINGLE_STEP 0x4

40
/* Include definitions for instructions classes and implementations flags */
41
//#define PPC_DEBUG_DISAS
42
//#define DO_PPC_STATISTICS
B
bellard 已提交
43

44
#ifdef PPC_DEBUG_DISAS
45
#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
46 47 48
#else
#  define LOG_DISAS(...) do { } while (0)
#endif
49 50
/*****************************************************************************/
/* Code translation helpers                                                  */
B
bellard 已提交
51

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

P
pbrook 已提交
80 81 82 83
#include "gen-icount.h"

void ppc_translate_init(void)
{
A
aurel32 已提交
84 85
    int i;
    char* p;
86
    size_t cpu_reg_names_size;
P
pbrook 已提交
87
    static int done_init = 0;
A
aurel32 已提交
88

P
pbrook 已提交
89 90
    if (done_init)
        return;
A
aurel32 已提交
91

P
pbrook 已提交
92 93
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");

A
aurel32 已提交
94
    p = cpu_reg_names;
95
    cpu_reg_names_size = sizeof(cpu_reg_names);
A
aurel32 已提交
96 97

    for (i = 0; i < 8; i++) {
98
        snprintf(p, cpu_reg_names_size, "crf%d", i);
P
pbrook 已提交
99 100
        cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
                                            offsetof(CPUState, crf[i]), p);
A
aurel32 已提交
101
        p += 5;
102
        cpu_reg_names_size -= 5;
A
aurel32 已提交
103 104
    }

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

119
        snprintf(p, cpu_reg_names_size, "fp%d", i);
P
pbrook 已提交
120 121
        cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                            offsetof(CPUState, fpr[i]), p);
A
aurel32 已提交
122
        p += (i < 10) ? 4 : 5;
123
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
A
aurel32 已提交
124

125
        snprintf(p, cpu_reg_names_size, "avr%dH", i);
126
#ifdef HOST_WORDS_BIGENDIAN
127 128 129
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                             offsetof(CPUState, avr[i].u64[0]), p);
#else
P
pbrook 已提交
130
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
131 132
                                             offsetof(CPUState, avr[i].u64[1]), p);
#endif
133
        p += (i < 10) ? 6 : 7;
134
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
A
aurel32 已提交
135

136
        snprintf(p, cpu_reg_names_size, "avr%dL", i);
137
#ifdef HOST_WORDS_BIGENDIAN
138 139 140
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                             offsetof(CPUState, avr[i].u64[1]), p);
#else
P
pbrook 已提交
141
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
142 143
                                             offsetof(CPUState, avr[i].u64[0]), p);
#endif
144
        p += (i < 10) ? 6 : 7;
145
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
A
aurel32 已提交
146
    }
A
aurel32 已提交
147

P
pbrook 已提交
148
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
149 150
                                 offsetof(CPUState, nip), "nip");

151 152 153
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
                                 offsetof(CPUState, msr), "msr");

P
pbrook 已提交
154
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
155 156
                                 offsetof(CPUState, ctr), "ctr");

P
pbrook 已提交
157
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
158 159
                                offsetof(CPUState, lr), "lr");

D
David Gibson 已提交
160 161 162 163 164
#if defined(TARGET_PPC64)
    cpu_cfar = tcg_global_mem_new(TCG_AREG0,
                                  offsetof(CPUState, cfar), "cfar");
#endif

P
pbrook 已提交
165
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
166 167
                                 offsetof(CPUState, xer), "xer");

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

P
pbrook 已提交
172 173
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
                                       offsetof(CPUState, fpscr), "fpscr");
174

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

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

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

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

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

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

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

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

250
    tcg_temp_free_i32(t0);
251 252
}

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

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

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

B
Blue Swirl 已提交
285
static inline void gen_exception(DisasContext *ctx, uint32_t excp)
A
aurel32 已提交
286 287 288 289 290 291 292 293 294 295
{
    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);
}
296

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

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

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

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

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

B
bellard 已提交
328
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
329 330 331 332
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)

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

334
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
335 336 337 338
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)

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

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

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

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

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

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

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

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

B
Blue Swirl 已提交
434
static inline uint32_t BD(uint32_t opcode)
B
bellard 已提交
435 436 437 438 439 440 441 442 443 444 445 446
{
    return (opcode >> 0) & 0xFFFC;
}

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

/* Create a mask between <start> and <end> bits */
B
Blue Swirl 已提交
447
static inline target_ulong MASK(uint32_t start, uint32_t end)
B
bellard 已提交
448
{
449
    target_ulong ret;
B
bellard 已提交
450

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

    return ret;
}

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

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

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

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

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

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

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

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

601 602
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
603 604 605 606 607 608
    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) {
609 610
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
611
    } else {
612 613
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
614 615 616 617 618 619 620 621 622 623 624
    }
    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 已提交
625
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
626
{
627 628 629
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
630 631 632
}

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

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

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

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

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

B
bellard 已提交
746 747
/***                           Integer arithmetic                          ***/

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

754 755 756
    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 已提交
757
    t0 = tcg_temp_local_new();
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
    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 已提交
779 780
}

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

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

792 793 794 795
        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 已提交
796
        } else {
797 798
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
        }
799 800 801 802
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
        gen_set_label(l1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
803 804
    } else
#endif
805 806 807 808 809 810 811 812
    {
        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);
813
    }
814 815
}

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

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

830
    if (add_ca) {
P
pbrook 已提交
831
        t1 = tcg_temp_local_new();
832 833
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
834 835
    } else {
        TCGV_UNUSED(t1);
836
    }
B
bellard 已提交
837

838 839 840 841 842 843 844 845 846 847
    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 已提交
848

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

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

static void gen_addic_(DisasContext *ctx)
947
{
948
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
949
}
B
Blue Swirl 已提交
950

951
/* addis */
B
Blue Swirl 已提交
952
static void gen_addis(DisasContext *ctx)
953
{
954 955 956 957 958 959 960 961
    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);
    }
962
}
963

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

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

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

/* mulhw  mulhw. */
B
Blue Swirl 已提交
1068
static void gen_mulhw(DisasContext *ctx)
1069
{
P
pbrook 已提交
1070
    TCGv_i64 t0, t1;
1071

P
pbrook 已提交
1072 1073
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
#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 已提交
1086 1087
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1088 1089
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1090
}
B
Blue Swirl 已提交
1091

1092
/* mulhwu  mulhwu.  */
B
Blue Swirl 已提交
1093
static void gen_mulhwu(DisasContext *ctx)
1094
{
P
pbrook 已提交
1095
    TCGv_i64 t0, t1;
1096

P
pbrook 已提交
1097 1098
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1099
#if defined(TARGET_PPC64)
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
    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 已提交
1111 1112
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1113 1114
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1115
}
B
Blue Swirl 已提交
1116

1117
/* mullw  mullw. */
B
Blue Swirl 已提交
1118
static void gen_mullw(DisasContext *ctx)
1119
{
1120 1121
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
1122
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1123 1124
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1125
}
B
Blue Swirl 已提交
1126

1127
/* mullwo  mullwo. */
B
Blue Swirl 已提交
1128
static void gen_mullwo(DisasContext *ctx)
1129
{
1130
    int l1;
P
pbrook 已提交
1131
    TCGv_i64 t0, t1;
1132

P
pbrook 已提交
1133 1134
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1135 1136 1137 1138 1139 1140 1141 1142 1143
    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)]);
1144
#endif
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
    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 已提交
1156 1157
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1158 1159
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1160
}
B
Blue Swirl 已提交
1161

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

1182
/* mulld  mulld. */
B
Blue Swirl 已提交
1183
static void gen_mulld(DisasContext *ctx)
1184
{
1185 1186 1187 1188
    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)]);
1189
}
1190 1191
/* mulldo  mulldo. */
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1192
#endif
1193 1194

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

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

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

/* Common subf function */
B
Blue Swirl 已提交
1238 1239 1240
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 已提交
1241
{
1242
    TCGv t0, t1;
1243

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

1251
    if (add_ca) {
P
pbrook 已提交
1252
        t1 = tcg_temp_local_new();
1253 1254
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
1255 1256
    } else {
        TCGV_UNUSED(t1);
1257
    }
B
bellard 已提交
1258

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2093
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
B
Blue Swirl 已提交
2094
static void gen_f##name(DisasContext *ctx)                                    \
2095
{                                                                             \
2096
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2097
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2098 2099
        return;                                                               \
    }                                                                         \
2100 2101
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2102
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2103 2104 2105
    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 已提交
2106 2107
}

2108
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
B
Blue Swirl 已提交
2109
static void gen_f##name(DisasContext *ctx)                                    \
2110
{                                                                             \
2111
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2112
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2113 2114
        return;                                                               \
    }                                                                         \
2115 2116
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2117
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2118 2119 2120
    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 已提交
2121 2122
}

2123
/* fadd - fadds */
2124
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2125
/* fdiv - fdivs */
2126
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2127
/* fmul - fmuls */
2128
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2129

2130
/* fre */
2131
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2132

2133
/* fres */
2134
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2135

2136
/* frsqrte */
2137 2138 2139
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
B
Blue Swirl 已提交
2140
static void gen_frsqrtes(DisasContext *ctx)
2141
{
A
aurel32 已提交
2142
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2143
        gen_exception(ctx, POWERPC_EXCP_FPU);
A
aurel32 已提交
2144 2145
        return;
    }
2146 2147
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2148 2149 2150 2151
    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);
2152
}
B
bellard 已提交
2153

2154
/* fsel */
2155
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2156
/* fsub - fsubs */
2157
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2158
/* Optional: */
B
Blue Swirl 已提交
2159

2160
/* fsqrt */
B
Blue Swirl 已提交
2161
static void gen_fsqrt(DisasContext *ctx)
2162
{
2163
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2164
        gen_exception(ctx, POWERPC_EXCP_FPU);
2165 2166
        return;
    }
2167 2168
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2169
    gen_reset_fpstatus();
A
aurel32 已提交
2170 2171
    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);
2172
}
B
bellard 已提交
2173

B
Blue Swirl 已提交
2174
static void gen_fsqrts(DisasContext *ctx)
B
bellard 已提交
2175
{
2176
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2177
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2178 2179
        return;
    }
2180 2181
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2182
    gen_reset_fpstatus();
A
aurel32 已提交
2183 2184 2185
    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 已提交
2186 2187 2188
}

/***                     Floating-Point multiply-and-add                   ***/
2189
/* fmadd - fmadds */
2190
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2191
/* fmsub - fmsubs */
2192
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2193
/* fnmadd - fnmadds */
2194
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2195
/* fnmsub - fnmsubs */
2196
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2197 2198 2199

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

2214
/* frin */
2215
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2216
/* friz */
2217
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2218
/* frip */
2219
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2220
/* frim */
2221
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2222

B
bellard 已提交
2223
/***                         Floating-Point compare                        ***/
B
Blue Swirl 已提交
2224

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

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

2259 2260
/***                         Floating-point move                           ***/
/* fabs */
2261 2262
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2263 2264

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

/* fnabs */
2277 2278
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2279
/* fneg */
2280 2281
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2282

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

2285
/* mcrfs */
B
Blue Swirl 已提交
2286
static void gen_mcrfs(DisasContext *ctx)
B
bellard 已提交
2287
{
2288 2289
    int bfa;

2290
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2291
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2292 2293
        return;
    }
2294
    bfa = 4 * (7 - crfS(ctx->opcode));
2295 2296
    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 已提交
2297
    tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
B
bellard 已提交
2298 2299 2300
}

/* mffs */
B
Blue Swirl 已提交
2301
static void gen_mffs(DisasContext *ctx)
B
bellard 已提交
2302
{
2303
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2304
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2305 2306
        return;
    }
2307
    gen_reset_fpstatus();
A
aurel32 已提交
2308 2309
    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 已提交
2310 2311 2312
}

/* mtfsb0 */
B
Blue Swirl 已提交
2313
static void gen_mtfsb0(DisasContext *ctx)
B
bellard 已提交
2314
{
B
bellard 已提交
2315
    uint8_t crb;
2316

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

/* mtfsb1 */
B
Blue Swirl 已提交
2337
static void gen_mtfsb1(DisasContext *ctx)
B
bellard 已提交
2338
{
B
bellard 已提交
2339
    uint8_t crb;
2340

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

/* mtfsf */
B
Blue Swirl 已提交
2364
static void gen_mtfsf(DisasContext *ctx)
B
bellard 已提交
2365
{
2366
    TCGv_i32 t0;
B
blueswir1 已提交
2367
    int L = ctx->opcode & 0x02000000;
A
aurel32 已提交
2368

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

/* mtfsfi */
B
Blue Swirl 已提交
2390
static void gen_mtfsfi(DisasContext *ctx)
B
bellard 已提交
2391
{
2392
    int bf, sh;
2393 2394
    TCGv_i64 t0;
    TCGv_i32 t1;
2395

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

2417 2418
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
B
Blue Swirl 已提交
2419 2420
static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
                                      target_long maskl)
2421 2422 2423
{
    target_long simm = SIMM(ctx->opcode);

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

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

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

B
Blue Swirl 已提交
2493
static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510
{
    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);
}

2511
/***                             Integer load                              ***/
B
Blue Swirl 已提交
2512
static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2513 2514 2515 2516
{
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2517
static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2518 2519 2520 2521
{
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2522
static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2523 2524 2525
{
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2526
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2527
    }
A
aurel32 已提交
2528 2529
}

B
Blue Swirl 已提交
2530
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2531
{
A
aurel32 已提交
2532 2533
    if (unlikely(ctx->le_mode)) {
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2534
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2535 2536 2537 2538
        tcg_gen_ext16s_tl(arg1, arg1);
    } else {
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2539 2540
}

B
Blue Swirl 已提交
2541
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2542
{
A
aurel32 已提交
2543 2544
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2545
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2546
    }
A
aurel32 已提交
2547 2548
}

A
aurel32 已提交
2549
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
2550
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2551
{
B
blueswir1 已提交
2552
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2553
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2554 2555
        tcg_gen_bswap32_tl(arg1, arg1);
        tcg_gen_ext32s_tl(arg1, arg1);
A
aurel32 已提交
2556
    } else
A
aurel32 已提交
2557
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2558
}
A
aurel32 已提交
2559
#endif
A
aurel32 已提交
2560

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

B
Blue Swirl 已提交
2569
static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2570
{
A
aurel32 已提交
2571
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2572 2573
}

B
Blue Swirl 已提交
2574
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2575
{
A
aurel32 已提交
2576 2577 2578
    if (unlikely(ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2579
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2580 2581 2582 2583 2584
        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 已提交
2585 2586
}

B
Blue Swirl 已提交
2587
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2588
{
A
aurel32 已提交
2589
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2590 2591 2592
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2593 2594 2595 2596 2597
        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 已提交
2598 2599
}

B
Blue Swirl 已提交
2600
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2601
{
A
aurel32 已提交
2602
    if (unlikely(ctx->le_mode)) {
P
pbrook 已提交
2603
        TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
2604
        tcg_gen_bswap64_i64(t0, arg1);
A
aurel32 已提交
2605
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
P
pbrook 已提交
2606
        tcg_temp_free_i64(t0);
A
aurel32 已提交
2607
    } else
A
aurel32 已提交
2608
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2609 2610
}

2611
#define GEN_LD(name, ldop, opc, type)                                         \
B
Blue Swirl 已提交
2612
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2613
{                                                                             \
A
aurel32 已提交
2614 2615 2616 2617 2618
    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 已提交
2619
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2620 2621
}

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

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

2659
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
B
Blue Swirl 已提交
2660
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2661
{                                                                             \
A
aurel32 已提交
2662 2663 2664 2665 2666
    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 已提交
2667
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2668 2669
}

2670 2671 2672 2673 2674
#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 已提交
2675 2676

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

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

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

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

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

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

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

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

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

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

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

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

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

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

B
bellard 已提交
2915
/* stwbrx */
2916
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2917
{
A
aurel32 已提交
2918
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2919 2920 2921
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2922 2923 2924 2925 2926
        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 已提交
2927
}
2928
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2929 2930

/***                    Integer load and store multiple                    ***/
B
Blue Swirl 已提交
2931

2932
/* lmw */
B
Blue Swirl 已提交
2933
static void gen_lmw(DisasContext *ctx)
B
bellard 已提交
2934
{
A
aurel32 已提交
2935 2936 2937
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2938
    /* NIP cannot be restored if the memory exception comes from an helper */
2939
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2940 2941 2942
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rD(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2943 2944 2945
    gen_helper_lmw(t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2946 2947 2948
}

/* stmw */
B
Blue Swirl 已提交
2949
static void gen_stmw(DisasContext *ctx)
B
bellard 已提交
2950
{
A
aurel32 已提交
2951 2952 2953
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2954
    /* NIP cannot be restored if the memory exception comes from an helper */
2955
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2956 2957 2958
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rS(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2959 2960 2961
    gen_helper_stmw(t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2962 2963 2964
}

/***                    Integer load and store strings                     ***/
2965

B
bellard 已提交
2966
/* lswi */
2967
/* PowerPC32 specification says we must generate an exception if
2968 2969 2970 2971
 * 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 已提交
2972
static void gen_lswi(DisasContext *ctx)
B
bellard 已提交
2973
{
2974 2975
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
2976 2977
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
2978
    int ra = rA(ctx->opcode);
B
bellard 已提交
2979 2980 2981 2982 2983
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
2984 2985 2986
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
A
aurel32 已提交
2987
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
2988
        return;
B
bellard 已提交
2989
    }
A
aurel32 已提交
2990
    gen_set_access_type(ctx, ACCESS_INT);
2991
    /* NIP cannot be restored if the memory exception comes from an helper */
2992
    gen_update_nip(ctx, ctx->nip - 4);
2993
    t0 = tcg_temp_new();
A
aurel32 已提交
2994
    gen_addr_register(ctx, t0);
2995 2996 2997 2998 2999 3000
    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 已提交
3001 3002 3003
}

/* lswx */
B
Blue Swirl 已提交
3004
static void gen_lswx(DisasContext *ctx)
B
bellard 已提交
3005
{
A
aurel32 已提交
3006 3007 3008
    TCGv t0;
    TCGv_i32 t1, t2, t3;
    gen_set_access_type(ctx, ACCESS_INT);
3009
    /* NIP cannot be restored if the memory exception comes from an helper */
3010
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3011 3012 3013 3014 3015
    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));
3016 3017 3018 3019 3020
    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 已提交
3021 3022 3023
}

/* stswi */
B
Blue Swirl 已提交
3024
static void gen_stswi(DisasContext *ctx)
B
bellard 已提交
3025
{
A
aurel32 已提交
3026 3027
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3028
    int nb = NB(ctx->opcode);
A
aurel32 已提交
3029
    gen_set_access_type(ctx, ACCESS_INT);
3030
    /* NIP cannot be restored if the memory exception comes from an helper */
3031
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3032 3033
    t0 = tcg_temp_new();
    gen_addr_register(ctx, t0);
B
bellard 已提交
3034 3035
    if (nb == 0)
        nb = 32;
3036
    t1 = tcg_const_i32(nb);
A
aurel32 已提交
3037
    t2 = tcg_const_i32(rS(ctx->opcode));
3038 3039 3040 3041
    gen_helper_stsw(t0, t1, t2);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3042 3043 3044
}

/* stswx */
B
Blue Swirl 已提交
3045
static void gen_stswx(DisasContext *ctx)
B
bellard 已提交
3046
{
A
aurel32 已提交
3047 3048 3049
    TCGv t0;
    TCGv_i32 t1, t2;
    gen_set_access_type(ctx, ACCESS_INT);
3050
    /* NIP cannot be restored if the memory exception comes from an helper */
3051
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3052 3053 3054
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_temp_new_i32();
3055 3056
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
    tcg_gen_andi_i32(t1, t1, 0x7F);
A
aurel32 已提交
3057
    t2 = tcg_const_i32(rS(ctx->opcode));
3058 3059 3060 3061
    gen_helper_stsw(t0, t1, t2);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3062 3063 3064 3065
}

/***                        Memory synchronisation                         ***/
/* eieio */
B
Blue Swirl 已提交
3066
static void gen_eieio(DisasContext *ctx)
B
bellard 已提交
3067 3068 3069 3070
{
}

/* isync */
B
Blue Swirl 已提交
3071
static void gen_isync(DisasContext *ctx)
B
bellard 已提交
3072
{
A
aurel32 已提交
3073
    gen_stop_exception(ctx);
B
bellard 已提交
3074 3075
}

3076
/* lwarx */
B
Blue Swirl 已提交
3077
static void gen_lwarx(DisasContext *ctx)
B
bellard 已提交
3078
{
A
aurel32 已提交
3079
    TCGv t0;
3080
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3081 3082 3083
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3084
    gen_check_align(ctx, t0, 0x03);
3085
    gen_qemu_ld32u(ctx, gpr, t0);
3086
    tcg_gen_mov_tl(cpu_reserve, t0);
3087
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
3088
    tcg_temp_free(t0);
B
bellard 已提交
3089 3090
}

3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108
#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;

    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUState, reserve_ea));
    tcg_gen_movi_tl(t0, (size << 5) | reg);
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, reserve_info));
    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 已提交
3109
/* stwcx. */
B
Blue Swirl 已提交
3110
static void gen_stwcx_(DisasContext *ctx)
B
bellard 已提交
3111
{
A
aurel32 已提交
3112 3113 3114 3115
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3116
    gen_check_align(ctx, t0, 0x03);
3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133
#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
3134
    tcg_temp_free(t0);
B
bellard 已提交
3135 3136
}

J
j_mayer 已提交
3137 3138
#if defined(TARGET_PPC64)
/* ldarx */
B
Blue Swirl 已提交
3139
static void gen_ldarx(DisasContext *ctx)
J
j_mayer 已提交
3140
{
A
aurel32 已提交
3141
    TCGv t0;
3142
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3143 3144 3145
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3146
    gen_check_align(ctx, t0, 0x07);
3147
    gen_qemu_ld64(ctx, gpr, t0);
3148
    tcg_gen_mov_tl(cpu_reserve, t0);
3149
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
3150
    tcg_temp_free(t0);
J
j_mayer 已提交
3151 3152 3153
}

/* stdcx. */
B
Blue Swirl 已提交
3154
static void gen_stdcx_(DisasContext *ctx)
J
j_mayer 已提交
3155
{
A
aurel32 已提交
3156 3157 3158 3159
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3160
    gen_check_align(ctx, t0, 0x07);
3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176
#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
3177
    tcg_temp_free(t0);
J
j_mayer 已提交
3178 3179 3180
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3181
/* sync */
B
Blue Swirl 已提交
3182
static void gen_sync(DisasContext *ctx)
B
bellard 已提交
3183 3184 3185
{
}

3186
/* wait */
B
Blue Swirl 已提交
3187
static void gen_wait(DisasContext *ctx)
3188
{
3189 3190 3191
    TCGv_i32 t0 = tcg_temp_new_i32();
    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
    tcg_temp_free_i32(t0);
3192
    /* Stop translation, as the CPU is supposed to sleep from now */
A
aurel32 已提交
3193
    gen_exception_err(ctx, EXCP_HLT, 1);
3194 3195
}

B
bellard 已提交
3196
/***                         Floating-point load                           ***/
3197
#define GEN_LDF(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
3198
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3199
{                                                                             \
3200
    TCGv EA;                                                                  \
3201
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3202
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3203 3204
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3205
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3206
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3207 3208
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3209
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3210 3211
}

3212
#define GEN_LDUF(name, ldop, opc, type)                                       \
B
Blue Swirl 已提交
3213
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3214
{                                                                             \
3215
    TCGv EA;                                                                  \
3216
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3217
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3218 3219
        return;                                                               \
    }                                                                         \
3220
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3221
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3222
        return;                                                               \
3223
    }                                                                         \
A
aurel32 已提交
3224
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3225
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3226 3227
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3228 3229
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3230 3231
}

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

3252
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3253
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3254
{                                                                             \
3255
    TCGv EA;                                                                  \
3256
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3257
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3258 3259
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3260
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3261
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3262 3263
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3264
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3265 3266
}

3267 3268 3269 3270 3271 3272
#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 已提交
3273
static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3274 3275 3276
{
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
A
aurel32 已提交
3277
    gen_qemu_ld32u(ctx, t0, arg2);
3278 3279 3280 3281 3282
    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 已提交
3283

3284 3285 3286 3287
 /* lfd lfdu lfdux lfdx */
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3288 3289

/***                         Floating-point store                          ***/
3290
#define GEN_STF(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
3291
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3292
{                                                                             \
3293
    TCGv EA;                                                                  \
3294
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3295
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3296 3297
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3298
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3299
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3300 3301
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3302
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3303 3304
}

3305
#define GEN_STUF(name, stop, opc, type)                                       \
B
Blue Swirl 已提交
3306
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3307
{                                                                             \
3308
    TCGv EA;                                                                  \
3309
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3310
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3311 3312
        return;                                                               \
    }                                                                         \
3313
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3314
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3315
        return;                                                               \
3316
    }                                                                         \
A
aurel32 已提交
3317
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3318
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3319 3320
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3321 3322
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3323 3324
}

3325
#define GEN_STUXF(name, stop, opc, type)                                      \
B
Blue Swirl 已提交
3326
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3327
{                                                                             \
3328
    TCGv EA;                                                                  \
3329
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3330
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3331 3332
        return;                                                               \
    }                                                                         \
3333
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3334
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3335
        return;                                                               \
3336
    }                                                                         \
A
aurel32 已提交
3337
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3338
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3339 3340
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3341 3342
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3343 3344
}

3345
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3346
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3347
{                                                                             \
3348
    TCGv EA;                                                                  \
3349
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3350
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3351 3352
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3353
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3354
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3355 3356
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3357
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3358 3359
}

3360 3361 3362 3363 3364 3365
#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 已提交
3366
static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3367 3368 3369 3370 3371 3372
{
    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 已提交
3373
    gen_qemu_st32(ctx, t1, arg2);
3374 3375
    tcg_temp_free(t1);
}
B
bellard 已提交
3376 3377

/* stfd stfdu stfdux stfdx */
3378
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
B
bellard 已提交
3379
/* stfs stfsu stfsux stfsx */
3380
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3381 3382

/* Optional: */
B
Blue Swirl 已提交
3383
static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3384 3385 3386
{
    TCGv t0 = tcg_temp_new();
    tcg_gen_trunc_i64_tl(t0, arg1),
A
aurel32 已提交
3387
    gen_qemu_st32(ctx, t0, arg2);
3388 3389
    tcg_temp_free(t0);
}
B
bellard 已提交
3390
/* stfiwx */
3391
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3392

D
David Gibson 已提交
3393 3394 3395 3396 3397 3398 3399 3400
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 已提交
3401
/***                                Branch                                 ***/
B
Blue Swirl 已提交
3402
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3403 3404 3405
{
    TranslationBlock *tb;
    tb = ctx->tb;
3406 3407 3408 3409
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        dest = (uint32_t) dest;
#endif
B
bellard 已提交
3410
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3411
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3412
        tcg_gen_goto_tb(n);
3413
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3414
        tcg_gen_exit_tb((tcg_target_long)tb + n);
3415
    } else {
3416
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3417 3418
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3419
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3420 3421 3422
                ctx->exception == POWERPC_EXCP_BRANCH) {
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
A
aurel32 已提交
3423
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3424 3425 3426
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3427
                gen_debug_exception(ctx);
3428 3429
            }
        }
B
bellard 已提交
3430
        tcg_gen_exit_tb(0);
3431
    }
B
bellard 已提交
3432 3433
}

B
Blue Swirl 已提交
3434
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3435 3436
{
#if defined(TARGET_PPC64)
3437 3438
    if (ctx->sf_mode == 0)
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3439 3440
    else
#endif
3441
        tcg_gen_movi_tl(cpu_lr, nip);
3442 3443
}

B
bellard 已提交
3444
/* b ba bl bla */
B
Blue Swirl 已提交
3445
static void gen_b(DisasContext *ctx)
B
bellard 已提交
3446
{
3447
    target_ulong li, target;
B
bellard 已提交
3448

3449
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3450
    /* sign extend LI */
3451
#if defined(TARGET_PPC64)
3452 3453 3454
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
3455
#endif
3456
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3457
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
3458
        target = ctx->nip + li - 4;
B
bellard 已提交
3459
    else
3460
        target = li;
3461 3462
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
D
David Gibson 已提交
3463
    gen_update_cfar(ctx, ctx->nip);
3464
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3465 3466
}

3467 3468 3469 3470
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

B
Blue Swirl 已提交
3471
static inline void gen_bcond(DisasContext *ctx, int type)
3472 3473
{
    uint32_t bo = BO(ctx->opcode);
3474
    int l1;
3475
    TCGv target;
3476

3477
    ctx->exception = POWERPC_EXCP_BRANCH;
3478
    if (type == BCOND_LR || type == BCOND_CTR) {
P
pbrook 已提交
3479
        target = tcg_temp_local_new();
3480 3481 3482 3483
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3484 3485
    } else {
        TCGV_UNUSED(target);
3486
    }
3487 3488
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3489 3490 3491
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3492
        TCGv temp = tcg_temp_new();
3493
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3494
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3495 3496 3497
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3498
#if defined(TARGET_PPC64)
3499 3500 3501
        if (!ctx->sf_mode)
            tcg_gen_ext32u_tl(temp, cpu_ctr);
        else
3502
#endif
3503 3504 3505 3506 3507
            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);
3508
        }
P
pbrook 已提交
3509
        tcg_temp_free(temp);
3510 3511 3512 3513 3514
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
3515
        TCGv_i32 temp = tcg_temp_new_i32();
3516

3517
        if (bo & 0x8) {
3518 3519
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3520
        } else {
3521 3522
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3523
        }
P
pbrook 已提交
3524
        tcg_temp_free_i32(temp);
3525
    }
D
David Gibson 已提交
3526
    gen_update_cfar(ctx, ctx->nip);
3527
    if (type == BCOND_IM) {
3528 3529 3530 3531 3532 3533
        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 已提交
3534
        gen_set_label(l1);
3535
        gen_goto_tb(ctx, 1, ctx->nip);
3536
    } else {
3537
#if defined(TARGET_PPC64)
3538 3539 3540 3541 3542 3543 3544 3545 3546 3547
        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);
3548 3549
        else
#endif
3550
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
B
bellard 已提交
3551
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3552
    }
3553 3554
}

B
Blue Swirl 已提交
3555
static void gen_bc(DisasContext *ctx)
3556
{
3557 3558 3559
    gen_bcond(ctx, BCOND_IM);
}

B
Blue Swirl 已提交
3560
static void gen_bcctr(DisasContext *ctx)
3561
{
3562 3563 3564
    gen_bcond(ctx, BCOND_CTR);
}

B
Blue Swirl 已提交
3565
static void gen_bclr(DisasContext *ctx)
3566
{
3567 3568
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3569 3570

/***                      Condition register logical                       ***/
3571
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
B
Blue Swirl 已提交
3572
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3573
{                                                                             \
3574 3575
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
P
pbrook 已提交
3576
    TCGv_i32 t0, t1;                                                          \
3577
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
P
pbrook 已提交
3578
    t0 = tcg_temp_new_i32();                                                  \
3579
    if (sh > 0)                                                               \
3580
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3581
    else if (sh < 0)                                                          \
3582
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3583
    else                                                                      \
3584
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
P
pbrook 已提交
3585
    t1 = tcg_temp_new_i32();                                                  \
3586 3587
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3588
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3589
    else if (sh < 0)                                                          \
3590
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3591
    else                                                                      \
3592 3593
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3594
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3595 3596 3597
    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 已提交
3598 3599
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
B
bellard 已提交
3600 3601 3602
}

/* crand */
3603
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3604
/* crandc */
3605
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3606
/* creqv */
3607
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3608
/* crnand */
3609
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3610
/* crnor */
3611
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3612
/* cror */
3613
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3614
/* crorc */
3615
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3616
/* crxor */
3617
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
Blue Swirl 已提交
3618

3619
/* mcrf */
B
Blue Swirl 已提交
3620
static void gen_mcrf(DisasContext *ctx)
B
bellard 已提交
3621
{
A
aurel32 已提交
3622
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3623 3624 3625
}

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

3627
/* rfi (mem_idx only) */
B
Blue Swirl 已提交
3628
static void gen_rfi(DisasContext *ctx)
B
bellard 已提交
3629
{
3630
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3631
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3632 3633
#else
    /* Restore CPU state */
A
aurel32 已提交
3634
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3635
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3636
        return;
3637
    }
D
David Gibson 已提交
3638
    gen_update_cfar(ctx, ctx->nip);
3639
    gen_helper_rfi();
A
aurel32 已提交
3640
    gen_sync_exception(ctx);
3641
#endif
B
bellard 已提交
3642 3643
}

J
j_mayer 已提交
3644
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3645
static void gen_rfid(DisasContext *ctx)
J
j_mayer 已提交
3646 3647
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3648
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3649 3650
#else
    /* Restore CPU state */
A
aurel32 已提交
3651
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3652
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3653 3654
        return;
    }
D
David Gibson 已提交
3655
    gen_update_cfar(ctx, ctx->nip);
3656
    gen_helper_rfid();
A
aurel32 已提交
3657
    gen_sync_exception(ctx);
J
j_mayer 已提交
3658 3659 3660
#endif
}

B
Blue Swirl 已提交
3661
static void gen_hrfid(DisasContext *ctx)
3662 3663
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3664
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3665 3666
#else
    /* Restore CPU state */
A
aurel32 已提交
3667
    if (unlikely(ctx->mem_idx <= 1)) {
A
aurel32 已提交
3668
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3669 3670
        return;
    }
3671
    gen_helper_hrfid();
A
aurel32 已提交
3672
    gen_sync_exception(ctx);
3673 3674 3675 3676
#endif
}
#endif

B
bellard 已提交
3677
/* sc */
3678 3679 3680 3681 3682
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
B
Blue Swirl 已提交
3683
static void gen_sc(DisasContext *ctx)
B
bellard 已提交
3684
{
3685 3686 3687
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
A
aurel32 已提交
3688
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3689 3690 3691
}

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

3693
/* tw */
B
Blue Swirl 已提交
3694
static void gen_tw(DisasContext *ctx)
B
bellard 已提交
3695
{
3696
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3697 3698
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3699 3700
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
B
bellard 已提交
3701 3702 3703
}

/* twi */
B
Blue Swirl 已提交
3704
static void gen_twi(DisasContext *ctx)
B
bellard 已提交
3705
{
3706 3707
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3708 3709
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3710 3711 3712
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3713 3714
}

3715 3716
#if defined(TARGET_PPC64)
/* td */
B
Blue Swirl 已提交
3717
static void gen_td(DisasContext *ctx)
3718
{
3719
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3720 3721
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3722 3723
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
3724 3725 3726
}

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

B
bellard 已提交
3739
/***                          Processor control                            ***/
B
Blue Swirl 已提交
3740

3741
/* mcrxr */
B
Blue Swirl 已提交
3742
static void gen_mcrxr(DisasContext *ctx)
B
bellard 已提交
3743
{
A
aurel32 已提交
3744 3745
    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);
3746
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
B
bellard 已提交
3747 3748
}

A
aurel32 已提交
3749
/* mfcr mfocrf */
B
Blue Swirl 已提交
3750
static void gen_mfcr(DisasContext *ctx)
B
bellard 已提交
3751
{
3752
    uint32_t crm, crn;
3753

3754 3755
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3756
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3757
            crn = ctz32 (crm);
3758
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3759 3760
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3761
        }
3762
    } else {
A
aurel32 已提交
3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780
        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);
3781
    }
B
bellard 已提交
3782 3783 3784
}

/* mfmsr */
B
Blue Swirl 已提交
3785
static void gen_mfmsr(DisasContext *ctx)
B
bellard 已提交
3786
{
3787
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3788
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3789
#else
A
aurel32 已提交
3790
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3791
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3792
        return;
3793
    }
3794
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3795
#endif
B
bellard 已提交
3796 3797
}

3798
static void spr_noaccess(void *opaque, int gprn, int sprn)
3799
{
3800
#if 0
3801 3802
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
3803
#endif
3804 3805 3806
}
#define SPR_NOACCESS (&spr_noaccess)

B
bellard 已提交
3807
/* mfspr */
B
Blue Swirl 已提交
3808
static inline void gen_op_mfspr(DisasContext *ctx)
B
bellard 已提交
3809
{
A
aurel32 已提交
3810
    void (*read_cb)(void *opaque, int gprn, int sprn);
B
bellard 已提交
3811 3812
    uint32_t sprn = SPR(ctx->opcode);

3813
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3814
    if (ctx->mem_idx == 2)
3815
        read_cb = ctx->spr_cb[sprn].hea_read;
A
aurel32 已提交
3816
    else if (ctx->mem_idx)
3817 3818
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3819
#endif
3820
        read_cb = ctx->spr_cb[sprn].uea_read;
3821 3822
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3823
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3824 3825
        } else {
            /* Privilege exception */
3826 3827 3828 3829 3830
            /* 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) {
3831
                qemu_log("Trying to read privileged spr %d %03x at "
3832 3833 3834
                         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);
3835
            }
A
aurel32 已提交
3836
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
3837
        }
3838 3839
    } else {
        /* Not defined */
3840
        qemu_log("Trying to read invalid spr %d %03x at "
3841 3842
                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3843
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3844
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3845 3846 3847
    }
}

B
Blue Swirl 已提交
3848
static void gen_mfspr(DisasContext *ctx)
B
bellard 已提交
3849
{
3850
    gen_op_mfspr(ctx);
3851
}
3852 3853

/* mftb */
B
Blue Swirl 已提交
3854
static void gen_mftb(DisasContext *ctx)
3855 3856
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3857 3858
}

A
aurel32 已提交
3859
/* mtcrf mtocrf*/
B
Blue Swirl 已提交
3860
static void gen_mtcrf(DisasContext *ctx)
B
bellard 已提交
3861
{
3862
    uint32_t crm, crn;
3863

3864
    crm = CRM(ctx->opcode);
M
malc 已提交
3865 3866 3867
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
3868
            crn = ctz32 (crm);
M
malc 已提交
3869
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
3870 3871
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
3872 3873
            tcg_temp_free_i32(temp);
        }
3874
    } else {
A
aurel32 已提交
3875 3876 3877 3878 3879 3880 3881 3882
        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 已提交
3883
        tcg_temp_free_i32(temp);
3884
    }
B
bellard 已提交
3885 3886 3887
}

/* mtmsr */
J
j_mayer 已提交
3888
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3889
static void gen_mtmsrd(DisasContext *ctx)
J
j_mayer 已提交
3890 3891
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3892
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3893
#else
A
aurel32 已提交
3894
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3895
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3896 3897
        return;
    }
3898 3899
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3900 3901 3902 3903 3904
        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);
3905
    } else {
3906 3907 3908 3909
        /* 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
         */
3910
        gen_update_nip(ctx, ctx->nip);
3911
        gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3912 3913
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3914
        gen_stop_exception(ctx);
3915
    }
J
j_mayer 已提交
3916 3917 3918 3919
#endif
}
#endif

B
Blue Swirl 已提交
3920
static void gen_mtmsr(DisasContext *ctx)
B
bellard 已提交
3921
{
3922
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3923
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3924
#else
A
aurel32 已提交
3925
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3926
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3927
        return;
3928
    }
3929 3930
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3931 3932 3933 3934 3935
        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);
3936
    } else {
3937 3938
        TCGv msr = tcg_temp_new();

3939 3940 3941 3942
        /* 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
         */
3943
        gen_update_nip(ctx, ctx->nip);
3944
#if defined(TARGET_PPC64)
3945 3946 3947
        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)]);
3948
#endif
3949
        gen_helper_store_msr(msr);
3950
        /* Must stop the translation as machine state (may have) changed */
3951
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3952
        gen_stop_exception(ctx);
3953
    }
3954
#endif
B
bellard 已提交
3955 3956 3957
}

/* mtspr */
B
Blue Swirl 已提交
3958
static void gen_mtspr(DisasContext *ctx)
B
bellard 已提交
3959
{
A
aurel32 已提交
3960
    void (*write_cb)(void *opaque, int sprn, int gprn);
B
bellard 已提交
3961 3962
    uint32_t sprn = SPR(ctx->opcode);

3963
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3964
    if (ctx->mem_idx == 2)
3965
        write_cb = ctx->spr_cb[sprn].hea_write;
A
aurel32 已提交
3966
    else if (ctx->mem_idx)
3967 3968
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
3969
#endif
3970
        write_cb = ctx->spr_cb[sprn].uea_write;
3971 3972
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3973
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
3974 3975
        } else {
            /* Privilege exception */
3976
            qemu_log("Trying to write privileged spr %d %03x at "
3977 3978 3979
                     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 已提交
3980
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3981
        }
3982 3983
    } else {
        /* Not defined */
3984
        qemu_log("Trying to write invalid spr %d %03x at "
3985 3986
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3987
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3988
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3989 3990 3991 3992
    }
}

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

3994
/* dcbf */
B
Blue Swirl 已提交
3995
static void gen_dcbf(DisasContext *ctx)
B
bellard 已提交
3996
{
J
j_mayer 已提交
3997
    /* XXX: specification says this is treated as a load by the MMU */
A
aurel32 已提交
3998 3999 4000 4001 4002
    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);
4003
    tcg_temp_free(t0);
B
bellard 已提交
4004 4005 4006
}

/* dcbi (Supervisor only) */
B
Blue Swirl 已提交
4007
static void gen_dcbi(DisasContext *ctx)
B
bellard 已提交
4008
{
4009
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4010
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4011
#else
A
aurel32 已提交
4012
    TCGv EA, val;
A
aurel32 已提交
4013
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4014
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4015
        return;
4016
    }
P
pbrook 已提交
4017
    EA = tcg_temp_new();
A
aurel32 已提交
4018 4019
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
4020
    val = tcg_temp_new();
4021
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
4022 4023
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
4024 4025
    tcg_temp_free(val);
    tcg_temp_free(EA);
4026
#endif
B
bellard 已提交
4027 4028 4029
}

/* dcdst */
B
Blue Swirl 已提交
4030
static void gen_dcbst(DisasContext *ctx)
B
bellard 已提交
4031
{
4032
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
4033 4034 4035 4036 4037
    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);
4038
    tcg_temp_free(t0);
B
bellard 已提交
4039 4040 4041
}

/* dcbt */
B
Blue Swirl 已提交
4042
static void gen_dcbt(DisasContext *ctx)
B
bellard 已提交
4043
{
4044
    /* interpreted as no-op */
4045 4046 4047
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4048 4049 4050
}

/* dcbtst */
B
Blue Swirl 已提交
4051
static void gen_dcbtst(DisasContext *ctx)
B
bellard 已提交
4052
{
4053
    /* interpreted as no-op */
4054 4055 4056
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4057 4058 4059
}

/* dcbz */
B
Blue Swirl 已提交
4060
static void gen_dcbz(DisasContext *ctx)
B
bellard 已提交
4061
{
A
aurel32 已提交
4062 4063
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4064 4065
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4066 4067
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4068 4069
    gen_helper_dcbz(t0);
    tcg_temp_free(t0);
4070 4071
}

B
Blue Swirl 已提交
4072
static void gen_dcbz_970(DisasContext *ctx)
4073
{
A
aurel32 已提交
4074 4075
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4076 4077
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4078 4079
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4080
    if (ctx->opcode & 0x00200000)
4081
        gen_helper_dcbz(t0);
4082
    else
4083 4084
        gen_helper_dcbz_970(t0);
    tcg_temp_free(t0);
B
bellard 已提交
4085 4086
}

4087
/* dst / dstt */
B
Blue Swirl 已提交
4088
static void gen_dst(DisasContext *ctx)
4089 4090 4091 4092 4093 4094 4095 4096 4097
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }
}

/* dstst /dststt */
B
Blue Swirl 已提交
4098
static void gen_dstst(DisasContext *ctx)
4099 4100 4101 4102 4103 4104 4105 4106 4107 4108
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }

}

/* dss / dssall */
B
Blue Swirl 已提交
4109
static void gen_dss(DisasContext *ctx)
4110 4111 4112 4113
{
    /* interpreted as no-op */
}

B
bellard 已提交
4114
/* icbi */
B
Blue Swirl 已提交
4115
static void gen_icbi(DisasContext *ctx)
B
bellard 已提交
4116
{
A
aurel32 已提交
4117 4118
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4119 4120
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4121 4122
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4123 4124
    gen_helper_icbi(t0);
    tcg_temp_free(t0);
B
bellard 已提交
4125 4126 4127 4128
}

/* Optional: */
/* dcba */
B
Blue Swirl 已提交
4129
static void gen_dcba(DisasContext *ctx)
B
bellard 已提交
4130
{
4131 4132 4133 4134
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4135 4136 4137 4138
}

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

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

/* mfsrin */
B
Blue Swirl 已提交
4158
static void gen_mfsrin(DisasContext *ctx)
B
bellard 已提交
4159
{
4160
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4161
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4162
#else
4163
    TCGv t0;
A
aurel32 已提交
4164
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4165
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4166
        return;
4167
    }
4168 4169 4170 4171 4172
    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);
4173
#endif
B
bellard 已提交
4174 4175 4176
}

/* mtsr */
B
Blue Swirl 已提交
4177
static void gen_mtsr(DisasContext *ctx)
B
bellard 已提交
4178
{
4179
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4180
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4181
#else
4182
    TCGv t0;
A
aurel32 已提交
4183
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4184
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4185
        return;
4186
    }
4187 4188 4189
    t0 = tcg_const_tl(SR(ctx->opcode));
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
    tcg_temp_free(t0);
4190
#endif
B
bellard 已提交
4191 4192 4193
}

/* mtsrin */
B
Blue Swirl 已提交
4194
static void gen_mtsrin(DisasContext *ctx)
B
bellard 已提交
4195
{
4196
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4197
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4198
#else
4199
    TCGv t0;
A
aurel32 已提交
4200
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4201
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4202
        return;
4203
    }
4204 4205 4206 4207 4208
    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);
4209
#endif
B
bellard 已提交
4210 4211
}

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

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

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

/* mtsr */
B
Blue Swirl 已提交
4252
static void gen_mtsr_64b(DisasContext *ctx)
4253 4254
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4255
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4256
#else
4257
    TCGv t0;
A
aurel32 已提交
4258
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4259
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4260 4261
        return;
    }
4262
    t0 = tcg_const_tl(SR(ctx->opcode));
B
blueswir1 已提交
4263
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4264
    tcg_temp_free(t0);
4265 4266 4267 4268
#endif
}

/* mtsrin */
B
Blue Swirl 已提交
4269
static void gen_mtsrin_64b(DisasContext *ctx)
4270 4271
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4272
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4273
#else
4274
    TCGv t0;
A
aurel32 已提交
4275
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4276
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4277 4278
        return;
    }
4279 4280 4281
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
B
blueswir1 已提交
4282
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4283
    tcg_temp_free(t0);
4284 4285
#endif
}
B
blueswir1 已提交
4286 4287

/* slbmte */
B
Blue Swirl 已提交
4288
static void gen_slbmte(DisasContext *ctx)
B
blueswir1 已提交
4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300
{
#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
}

4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327
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
}
4328 4329
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4330
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4331
/* Optional & mem_idx only: */
B
Blue Swirl 已提交
4332

4333
/* tlbia */
B
Blue Swirl 已提交
4334
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4335
{
4336
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4337
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4338
#else
A
aurel32 已提交
4339
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4340
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4341
        return;
4342
    }
4343
    gen_helper_tlbia();
4344
#endif
B
bellard 已提交
4345 4346
}

B
blueswir1 已提交
4347
/* tlbiel */
B
Blue Swirl 已提交
4348
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360
{
#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 已提交
4361
/* tlbie */
B
Blue Swirl 已提交
4362
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4363
{
4364
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4365
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4366
#else
A
aurel32 已提交
4367
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4368
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4369
        return;
4370
    }
4371
#if defined(TARGET_PPC64)
4372 4373 4374 4375 4376 4377
    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
4378
#endif
4379
        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4380
#endif
B
bellard 已提交
4381 4382 4383
}

/* tlbsync */
B
Blue Swirl 已提交
4384
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4385
{
4386
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4387
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4388
#else
A
aurel32 已提交
4389
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4390
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4391
        return;
4392 4393 4394 4395
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4396
    gen_stop_exception(ctx);
4397
#endif
B
bellard 已提交
4398 4399
}

J
j_mayer 已提交
4400 4401
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4402
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4403 4404
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4405
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4406
#else
A
aurel32 已提交
4407
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4408
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4409 4410
        return;
    }
4411
    gen_helper_slbia();
J
j_mayer 已提交
4412 4413 4414 4415
#endif
}

/* slbie */
B
Blue Swirl 已提交
4416
static void gen_slbie(DisasContext *ctx)
J
j_mayer 已提交
4417 4418
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4419
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4420
#else
A
aurel32 已提交
4421
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4422
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4423 4424
        return;
    }
4425
    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4426 4427 4428 4429
#endif
}
#endif

B
bellard 已提交
4430 4431
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4432

4433
/* eciwx */
B
Blue Swirl 已提交
4434
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4435
{
A
aurel32 已提交
4436
    TCGv t0;
4437
    /* Should check EAR[E] ! */
A
aurel32 已提交
4438 4439 4440
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4441
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4442
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4443
    tcg_temp_free(t0);
4444 4445 4446
}

/* ecowx */
B
Blue Swirl 已提交
4447
static void gen_ecowx(DisasContext *ctx)
4448
{
A
aurel32 已提交
4449
    TCGv t0;
4450
    /* Should check EAR[E] ! */
A
aurel32 已提交
4451 4452 4453
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4454
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4455
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4456
    tcg_temp_free(t0);
4457 4458 4459
}

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

4461
/* abs - abs. */
B
Blue Swirl 已提交
4462
static void gen_abs(DisasContext *ctx)
4463
{
4464 4465 4466 4467 4468 4469 4470 4471
    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);
4472
    if (unlikely(Rc(ctx->opcode) != 0))
4473
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4474 4475 4476
}

/* abso - abso. */
B
Blue Swirl 已提交
4477
static void gen_abso(DisasContext *ctx)
4478
{
4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493
    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);
4494
    if (unlikely(Rc(ctx->opcode) != 0))
4495
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4496 4497 4498
}

/* clcs */
B
Blue Swirl 已提交
4499
static void gen_clcs(DisasContext *ctx)
4500
{
4501 4502 4503
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
4504
    /* Rc=1 sets CR0 to an undefined state */
4505 4506 4507
}

/* div - div. */
B
Blue Swirl 已提交
4508
static void gen_div(DisasContext *ctx)
4509
{
4510
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4511
    if (unlikely(Rc(ctx->opcode) != 0))
4512
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4513 4514 4515
}

/* divo - divo. */
B
Blue Swirl 已提交
4516
static void gen_divo(DisasContext *ctx)
4517
{
4518
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4519
    if (unlikely(Rc(ctx->opcode) != 0))
4520
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4521 4522 4523
}

/* divs - divs. */
B
Blue Swirl 已提交
4524
static void gen_divs(DisasContext *ctx)
4525
{
4526
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4527
    if (unlikely(Rc(ctx->opcode) != 0))
4528
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4529 4530 4531
}

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

/* doz - doz. */
B
Blue Swirl 已提交
4540
static void gen_doz(DisasContext *ctx)
4541
{
4542 4543 4544 4545 4546 4547 4548 4549
    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);
4550
    if (unlikely(Rc(ctx->opcode) != 0))
4551
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4552 4553 4554
}

/* dozo - dozo. */
B
Blue Swirl 已提交
4555
static void gen_dozo(DisasContext *ctx)
4556
{
4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578
    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);
4579
    if (unlikely(Rc(ctx->opcode) != 0))
4580
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4581 4582 4583
}

/* dozi */
B
Blue Swirl 已提交
4584
static void gen_dozi(DisasContext *ctx)
4585
{
4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596
    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)]);
4597 4598 4599
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4600
static void gen_lscbx(DisasContext *ctx)
4601
{
4602 4603 4604 4605
    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));
4606

A
aurel32 已提交
4607
    gen_addr_reg_index(ctx, t0);
4608
    /* NIP cannot be restored if the memory exception comes from an helper */
4609
    gen_update_nip(ctx, ctx->nip - 4);
4610 4611 4612 4613
    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 已提交
4614
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4615
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4616
    if (unlikely(Rc(ctx->opcode) != 0))
4617 4618
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4619 4620 4621
}

/* maskg - maskg. */
B
Blue Swirl 已提交
4622
static void gen_maskg(DisasContext *ctx)
4623
{
4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642
    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);
4643
    if (unlikely(Rc(ctx->opcode) != 0))
4644
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4645 4646 4647
}

/* maskir - maskir. */
B
Blue Swirl 已提交
4648
static void gen_maskir(DisasContext *ctx)
4649
{
4650 4651 4652 4653 4654 4655 4656
    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);
4657
    if (unlikely(Rc(ctx->opcode) != 0))
4658
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4659 4660 4661
}

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

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

/* nabs - nabs. */
B
Blue Swirl 已提交
4709
static void gen_nabs(DisasContext *ctx)
4710
{
4711 4712 4713 4714 4715 4716 4717 4718
    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);
4719
    if (unlikely(Rc(ctx->opcode) != 0))
4720
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4721 4722 4723
}

/* nabso - nabso. */
B
Blue Swirl 已提交
4724
static void gen_nabso(DisasContext *ctx)
4725
{
4726 4727 4728 4729 4730 4731 4732 4733 4734 4735
    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));
4736
    if (unlikely(Rc(ctx->opcode) != 0))
4737
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4738 4739 4740
}

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

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

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

/* sleq - sleq. */
B
Blue Swirl 已提交
4793
static void gen_sleq(DisasContext *ctx)
4794
{
4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809
    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);
4810
    if (unlikely(Rc(ctx->opcode) != 0))
4811
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4812 4813 4814
}

/* sliq - sliq. */
B
Blue Swirl 已提交
4815
static void gen_sliq(DisasContext *ctx)
4816
{
4817 4818 4819 4820 4821 4822 4823 4824 4825 4826
    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);
4827
    if (unlikely(Rc(ctx->opcode) != 0))
4828
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4829 4830 4831
}

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

/* sllq - sllq. */
B
Blue Swirl 已提交
4850
static void gen_sllq(DisasContext *ctx)
4851
{
4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873
    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);
4874
    if (unlikely(Rc(ctx->opcode) != 0))
4875
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4876 4877 4878
}

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

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

/* sraq - sraq. */
B
Blue Swirl 已提交
4925
static void gen_sraq(DisasContext *ctx)
4926
{
4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952
    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);
4953
    if (unlikely(Rc(ctx->opcode) != 0))
4954
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4955 4956 4957
}

/* sre - sre. */
B
Blue Swirl 已提交
4958
static void gen_sre(DisasContext *ctx)
4959
{
4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970
    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);
4971
    if (unlikely(Rc(ctx->opcode) != 0))
4972
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4973 4974 4975
}

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

/* sreq */
B
Blue Swirl 已提交
4991
static void gen_sreq(DisasContext *ctx)
4992
{
4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007
    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);
5008
    if (unlikely(Rc(ctx->opcode) != 0))
5009
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5010 5011 5012
}

/* sriq */
B
Blue Swirl 已提交
5013
static void gen_sriq(DisasContext *ctx)
5014
{
5015 5016 5017 5018 5019 5020 5021 5022 5023 5024
    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);
5025
    if (unlikely(Rc(ctx->opcode) != 0))
5026
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5027 5028 5029
}

/* srliq */
B
Blue Swirl 已提交
5030
static void gen_srliq(DisasContext *ctx)
5031
{
5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042
    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);
5043
    if (unlikely(Rc(ctx->opcode) != 0))
5044
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5045 5046 5047
}

/* srlq */
B
Blue Swirl 已提交
5048
static void gen_srlq(DisasContext *ctx)
5049
{
5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072
    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);
5073
    if (unlikely(Rc(ctx->opcode) != 0))
5074
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5075 5076 5077
}

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

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

5102
/* dsa  */
B
Blue Swirl 已提交
5103
static void gen_dsa(DisasContext *ctx)
5104 5105
{
    /* XXX: TODO */
A
aurel32 已提交
5106
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5107 5108 5109
}

/* esa */
B
Blue Swirl 已提交
5110
static void gen_esa(DisasContext *ctx)
5111 5112
{
    /* XXX: TODO */
A
aurel32 已提交
5113
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5114 5115 5116
}

/* mfrom */
B
Blue Swirl 已提交
5117
static void gen_mfrom(DisasContext *ctx)
5118 5119
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5120
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5121
#else
A
aurel32 已提交
5122
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5123
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5124 5125
        return;
    }
5126
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5127 5128 5129 5130
#endif
}

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

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

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

5160
/* 74xx TLB management */
B
Blue Swirl 已提交
5161

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

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

5190
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5191

5192
/* clf */
B
Blue Swirl 已提交
5193
static void gen_clf(DisasContext *ctx)
5194 5195 5196 5197 5198
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5199
static void gen_cli(DisasContext *ctx)
5200
{
B
blueswir1 已提交
5201
    /* Cache line invalidate: privileged and treated as no-op */
5202
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5203
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5204
#else
A
aurel32 已提交
5205
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5206
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5207 5208 5209 5210 5211 5212
        return;
    }
#endif
}

/* dclst */
B
Blue Swirl 已提交
5213
static void gen_dclst(DisasContext *ctx)
5214 5215 5216 5217
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5218
static void gen_mfsri(DisasContext *ctx)
5219 5220
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5221
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5222
#else
5223 5224 5225
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5226
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5227
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5228 5229
        return;
    }
5230
    t0 = tcg_temp_new();
A
aurel32 已提交
5231
    gen_addr_reg_index(ctx, t0);
5232 5233 5234 5235
    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);
5236
    if (ra != 0 && ra != rd)
5237
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5238 5239 5240
#endif
}

B
Blue Swirl 已提交
5241
static void gen_rac(DisasContext *ctx)
5242 5243
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5244
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5245
#else
5246
    TCGv t0;
A
aurel32 已提交
5247
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5248
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5249 5250
        return;
    }
5251
    t0 = tcg_temp_new();
A
aurel32 已提交
5252
    gen_addr_reg_index(ctx, t0);
5253 5254
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
5255 5256 5257
#endif
}

B
Blue Swirl 已提交
5258
static void gen_rfsvc(DisasContext *ctx)
5259 5260
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5261
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5262
#else
A
aurel32 已提交
5263
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5264
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5265 5266
        return;
    }
5267
    gen_helper_rfsvc();
A
aurel32 已提交
5268
    gen_sync_exception(ctx);
5269 5270 5271 5272 5273 5274 5275 5276 5277
#endif
}

/* svc is not implemented for now */

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

/* lfq */
B
Blue Swirl 已提交
5278
static void gen_lfq(DisasContext *ctx)
5279
{
5280
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5281 5282 5283 5284 5285 5286 5287
    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);
5288
    tcg_temp_free(t0);
5289 5290 5291
}

/* lfqu */
B
Blue Swirl 已提交
5292
static void gen_lfqu(DisasContext *ctx)
5293 5294
{
    int ra = rA(ctx->opcode);
5295
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5296 5297 5298 5299 5300 5301 5302 5303
    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);
5304
    if (ra != 0)
5305 5306 5307
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5308 5309 5310
}

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

/* lfqx */
B
Blue Swirl 已提交
5330
static void gen_lfqx(DisasContext *ctx)
5331
{
5332
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5333 5334 5335 5336 5337 5338 5339
    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);
5340
    tcg_temp_free(t0);
5341 5342 5343
}

/* stfq */
B
Blue Swirl 已提交
5344
static void gen_stfq(DisasContext *ctx)
5345
{
5346
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5347 5348 5349 5350 5351 5352 5353
    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);
5354
    tcg_temp_free(t0);
5355 5356 5357
}

/* stfqu */
B
Blue Swirl 已提交
5358
static void gen_stfqu(DisasContext *ctx)
5359 5360
{
    int ra = rA(ctx->opcode);
5361
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5362 5363 5364 5365 5366 5367 5368 5369 5370
    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);
5371
    if (ra != 0)
5372 5373
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5374 5375 5376
}

/* stfqux */
B
Blue Swirl 已提交
5377
static void gen_stfqux(DisasContext *ctx)
5378 5379
{
    int ra = rA(ctx->opcode);
5380
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5381 5382 5383 5384 5385 5386 5387 5388 5389
    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);
5390
    if (ra != 0)
5391 5392
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5393 5394 5395
}

/* stfqx */
B
Blue Swirl 已提交
5396
static void gen_stfqx(DisasContext *ctx)
5397
{
5398
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5399 5400 5401 5402 5403 5404 5405
    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);
5406
    tcg_temp_free(t0);
5407 5408 5409
}

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

5411
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5412
static void gen_mfapidi(DisasContext *ctx)
5413 5414
{
    /* XXX: TODO */
A
aurel32 已提交
5415
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5416 5417
}

5418
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5419
static void gen_tlbiva(DisasContext *ctx)
5420 5421
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5422
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5423
#else
5424
    TCGv t0;
A
aurel32 已提交
5425
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5426
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5427 5428
        return;
    }
5429
    t0 = tcg_temp_new();
A
aurel32 已提交
5430
    gen_addr_reg_index(ctx, t0);
5431 5432
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(t0);
5433 5434 5435 5436
#endif
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5437 5438
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5439
{
5440 5441
    TCGv t0, t1;

P
pbrook 已提交
5442 5443
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5444

5445 5446 5447 5448 5449 5450 5451
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5452 5453 5454
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5455 5456 5457 5458 5459
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5460 5461 5462
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5463 5464 5465 5466 5467 5468 5469
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5470 5471 5472 5473
        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);
5474 5475 5476 5477 5478
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5479 5480 5481 5482
        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);
5483 5484 5485 5486 5487 5488 5489
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5490 5491
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5492 5493 5494 5495 5496
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5497 5498
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5499 5500 5501
        break;
    }
    if (opc2 & 0x04) {
5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525
        /* (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 已提交
5526
                if (opc3 & 0x02) {
5527 5528 5529 5530 5531 5532 5533
                    /* 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 已提交
5534
                if (opc3 & 0x02) {
5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547
                    /* 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);
5548
    }
5549 5550
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5551 5552
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5553
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5554 5555 5556
    }
}

5557
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5558
static void glue(gen_, name)(DisasContext *ctx)                               \
5559 5560 5561 5562 5563 5564
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5565
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5566
/* macchwo   - macchwo.   */
5567
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5568
/* macchws   - macchws.   */
5569
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5570
/* macchwso  - macchwso.  */
5571
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5572
/* macchwsu  - macchwsu.  */
5573
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5574
/* macchwsuo - macchwsuo. */
5575
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5576
/* macchwu   - macchwu.   */
5577
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5578
/* macchwuo  - macchwuo.  */
5579
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5580
/* machhw    - machhw.    */
5581
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5582
/* machhwo   - machhwo.   */
5583
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5584
/* machhws   - machhws.   */
5585
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5586
/* machhwso  - machhwso.  */
5587
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5588
/* machhwsu  - machhwsu.  */
5589
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5590
/* machhwsuo - machhwsuo. */
5591
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5592
/* machhwu   - machhwu.   */
5593
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5594
/* machhwuo  - machhwuo.  */
5595
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5596
/* maclhw    - maclhw.    */
5597
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5598
/* maclhwo   - maclhwo.   */
5599
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5600
/* maclhws   - maclhws.   */
5601
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5602
/* maclhwso  - maclhwso.  */
5603
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5604
/* maclhwu   - maclhwu.   */
5605
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5606
/* maclhwuo  - maclhwuo.  */
5607
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5608
/* maclhwsu  - maclhwsu.  */
5609
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5610
/* maclhwsuo - maclhwsuo. */
5611
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5612
/* nmacchw   - nmacchw.   */
5613
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5614
/* nmacchwo  - nmacchwo.  */
5615
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5616
/* nmacchws  - nmacchws.  */
5617
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5618
/* nmacchwso - nmacchwso. */
5619
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5620
/* nmachhw   - nmachhw.   */
5621
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5622
/* nmachhwo  - nmachhwo.  */
5623
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5624
/* nmachhws  - nmachhws.  */
5625
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5626
/* nmachhwso - nmachhwso. */
5627
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5628
/* nmaclhw   - nmaclhw.   */
5629
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5630
/* nmaclhwo  - nmaclhwo.  */
5631
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5632
/* nmaclhws  - nmaclhws.  */
5633
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5634
/* nmaclhwso - nmaclhwso. */
5635
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5636 5637

/* mulchw  - mulchw.  */
5638
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5639
/* mulchwu - mulchwu. */
5640
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5641
/* mulhhw  - mulhhw.  */
5642
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5643
/* mulhhwu - mulhhwu. */
5644
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5645
/* mullhw  - mullhw.  */
5646
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5647
/* mullhwu - mullhwu. */
5648
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5649 5650

/* mfdcr */
B
Blue Swirl 已提交
5651
static void gen_mfdcr(DisasContext *ctx)
5652 5653
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5654
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5655
#else
5656
    TCGv dcrn;
A
aurel32 已提交
5657
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5658
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5659 5660
        return;
    }
5661 5662 5663 5664 5665
    /* 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);
5666 5667 5668 5669
#endif
}

/* mtdcr */
B
Blue Swirl 已提交
5670
static void gen_mtdcr(DisasContext *ctx)
5671 5672
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5673
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5674
#else
5675
    TCGv dcrn;
A
aurel32 已提交
5676
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5677
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5678 5679
        return;
    }
5680 5681 5682 5683 5684
    /* 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);
5685 5686 5687 5688
#endif
}

/* mfdcrx */
5689
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5690
static void gen_mfdcrx(DisasContext *ctx)
5691 5692
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5693
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5694
#else
A
aurel32 已提交
5695
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5696
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5697 5698
        return;
    }
5699 5700 5701
    /* 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)]);
5702
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5703 5704 5705 5706
#endif
}

/* mtdcrx */
5707
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5708
static void gen_mtdcrx(DisasContext *ctx)
5709 5710
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5711
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5712
#else
A
aurel32 已提交
5713
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5714
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5715 5716
        return;
    }
5717 5718 5719
    /* 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)]);
5720
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5721 5722 5723
#endif
}

5724
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5725
static void gen_mfdcrux(DisasContext *ctx)
5726
{
5727 5728 5729
    /* 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)]);
5730 5731 5732 5733
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5734
static void gen_mtdcrux(DisasContext *ctx)
5735
{
5736 5737 5738
    /* 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)]);
5739 5740 5741
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5742
/* dccci */
B
Blue Swirl 已提交
5743
static void gen_dccci(DisasContext *ctx)
5744 5745
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5746
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5747
#else
A
aurel32 已提交
5748
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5749
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5750 5751 5752 5753 5754 5755 5756
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
B
Blue Swirl 已提交
5757
static void gen_dcread(DisasContext *ctx)
5758 5759
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5760
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5761
#else
A
aurel32 已提交
5762
    TCGv EA, val;
A
aurel32 已提交
5763
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5764
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5765 5766
        return;
    }
A
aurel32 已提交
5767
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5768
    EA = tcg_temp_new();
A
aurel32 已提交
5769
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5770
    val = tcg_temp_new();
A
aurel32 已提交
5771
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5772 5773 5774
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5775 5776 5777 5778
#endif
}

/* icbt */
B
Blue Swirl 已提交
5779
static void gen_icbt_40x(DisasContext *ctx)
5780 5781 5782 5783 5784 5785 5786 5787
{
    /* 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 已提交
5788
static void gen_iccci(DisasContext *ctx)
5789 5790
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5791
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5792
#else
A
aurel32 已提交
5793
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5794
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5795 5796 5797 5798 5799 5800 5801
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
B
Blue Swirl 已提交
5802
static void gen_icread(DisasContext *ctx)
5803 5804
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5805
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5806
#else
A
aurel32 已提交
5807
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5808
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5809 5810 5811 5812 5813 5814
        return;
    }
    /* interpreted as no-op */
#endif
}

A
aurel32 已提交
5815
/* rfci (mem_idx only) */
B
Blue Swirl 已提交
5816
static void gen_rfci_40x(DisasContext *ctx)
5817 5818
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5819
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5820
#else
A
aurel32 已提交
5821
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5822
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5823 5824 5825
        return;
    }
    /* Restore CPU state */
5826
    gen_helper_40x_rfci();
A
aurel32 已提交
5827
    gen_sync_exception(ctx);
5828 5829 5830
#endif
}

B
Blue Swirl 已提交
5831
static void gen_rfci(DisasContext *ctx)
5832 5833
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5834
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5835
#else
A
aurel32 已提交
5836
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5837
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5838 5839 5840
        return;
    }
    /* Restore CPU state */
5841
    gen_helper_rfci();
A
aurel32 已提交
5842
    gen_sync_exception(ctx);
5843 5844 5845 5846
#endif
}

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

5848
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5849
static void gen_rfdi(DisasContext *ctx)
5850 5851
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5852
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5853
#else
A
aurel32 已提交
5854
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5855
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5856 5857 5858
        return;
    }
    /* Restore CPU state */
5859
    gen_helper_rfdi();
A
aurel32 已提交
5860
    gen_sync_exception(ctx);
5861 5862 5863
#endif
}

5864
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5865
static void gen_rfmci(DisasContext *ctx)
5866 5867
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5868
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5869
#else
A
aurel32 已提交
5870
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5871
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5872 5873 5874
        return;
    }
    /* Restore CPU state */
5875
    gen_helper_rfmci();
A
aurel32 已提交
5876
    gen_sync_exception(ctx);
5877 5878
#endif
}
5879

5880
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5881

5882
/* tlbre */
B
Blue Swirl 已提交
5883
static void gen_tlbre_40x(DisasContext *ctx)
5884 5885
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5886
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5887
#else
A
aurel32 已提交
5888
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5889
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5890 5891 5892 5893
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5894
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5895 5896
        break;
    case 1:
5897
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5898 5899
        break;
    default:
A
aurel32 已提交
5900
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5901
        break;
5902
    }
5903 5904 5905
#endif
}

5906
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5907
static void gen_tlbsx_40x(DisasContext *ctx)
5908 5909
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5910
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5911
#else
5912
    TCGv t0;
A
aurel32 已提交
5913
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5914
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5915 5916
        return;
    }
5917
    t0 = tcg_temp_new();
A
aurel32 已提交
5918
    gen_addr_reg_index(ctx, t0);
5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929
    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);
    }
5930
#endif
B
bellard 已提交
5931 5932
}

5933
/* tlbwe */
B
Blue Swirl 已提交
5934
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
5935
{
5936
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5937
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5938
#else
A
aurel32 已提交
5939
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5940
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5941 5942 5943 5944
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5945
        gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5946 5947
        break;
    case 1:
5948
        gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5949 5950
        break;
    default:
A
aurel32 已提交
5951
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5952
        break;
5953
    }
5954 5955 5956
#endif
}

5957
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
5958

5959
/* tlbre */
B
Blue Swirl 已提交
5960
static void gen_tlbre_440(DisasContext *ctx)
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 5971 5972
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5973 5974
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
E
Edgar E. Iglesias 已提交
5975
            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], t0, cpu_gpr[rA(ctx->opcode)]);
5976 5977
            tcg_temp_free_i32(t0);
        }
5978 5979
        break;
    default:
A
aurel32 已提交
5980
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5981 5982 5983 5984 5985 5986
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5987
static void gen_tlbsx_440(DisasContext *ctx)
5988 5989
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5990
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5991
#else
5992
    TCGv t0;
A
aurel32 已提交
5993
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5994
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5995 5996
        return;
    }
5997
    t0 = tcg_temp_new();
A
aurel32 已提交
5998
    gen_addr_reg_index(ctx, t0);
5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009
    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);
    }
6010 6011 6012 6013
#endif
}

/* tlbwe */
B
Blue Swirl 已提交
6014
static void gen_tlbwe_440(DisasContext *ctx)
6015 6016
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6017
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6018
#else
A
aurel32 已提交
6019
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6020
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6021 6022 6023 6024 6025 6026
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6027 6028 6029 6030 6031
        {
            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);
        }
6032 6033
        break;
    default:
A
aurel32 已提交
6034
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6035 6036 6037 6038 6039
        break;
    }
#endif
}

A
Alexander Graf 已提交
6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 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
/* 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;
    }
6091
    gen_update_nip(ctx, ctx->nip - 4);
A
Alexander Graf 已提交
6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113
    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 已提交
6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146
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 已提交
6147

6148
/* wrtee */
B
Blue Swirl 已提交
6149
static void gen_wrtee(DisasContext *ctx)
6150 6151
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6152
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6153
#else
6154
    TCGv t0;
A
aurel32 已提交
6155
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6156
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6157 6158
        return;
    }
6159 6160 6161 6162 6163
    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 已提交
6164 6165 6166
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
6167
    gen_stop_exception(ctx);
6168 6169 6170 6171
#endif
}

/* wrteei */
B
Blue Swirl 已提交
6172
static void gen_wrteei(DisasContext *ctx)
6173 6174
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6175
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6176
#else
A
aurel32 已提交
6177
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6178
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6179 6180
        return;
    }
6181
    if (ctx->opcode & 0x00008000) {
6182 6183
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6184
        gen_stop_exception(ctx);
6185
    } else {
A
aurel32 已提交
6186
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6187
    }
6188 6189 6190
#endif
}

J
j_mayer 已提交
6191
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
6192

6193
/* dlmzb */
B
Blue Swirl 已提交
6194
static void gen_dlmzb(DisasContext *ctx)
6195
{
6196 6197 6198 6199
    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);
6200 6201 6202
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
6203
static void gen_mbar(DisasContext *ctx)
6204 6205 6206 6207 6208
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
A
Alexander Graf 已提交
6209
static void gen_msync_4xx(DisasContext *ctx)
6210 6211 6212 6213 6214
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6215
static void gen_icbt_440(DisasContext *ctx)
6216 6217 6218 6219 6220
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6221 6222
}

A
Alexander Graf 已提交
6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238
/* 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
}

6239 6240 6241
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

B
Blue Swirl 已提交
6242
static inline TCGv_ptr gen_avr_ptr(int reg)
A
aurel32 已提交
6243
{
A
aurel32 已提交
6244
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6245 6246 6247 6248
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

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

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

A
aurel32 已提交
6297
#define GEN_VR_LVE(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6298
static void gen_lve##name(DisasContext *ctx)                            \
A
aurel32 已提交
6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315
    {                                                                   \
        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 已提交
6316
static void gen_stve##name(DisasContext *ctx)                           \
A
aurel32 已提交
6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332
    {                                                                   \
        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);                                          \
    }

6333
GEN_VR_LDX(lvx, 0x07, 0x03);
6334
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6335
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6336

A
aurel32 已提交
6337 6338 6339 6340
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6341
GEN_VR_STX(svx, 0x07, 0x07);
6342
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6343
GEN_VR_STX(svxl, 0x07, 0x0F);
6344

A
aurel32 已提交
6345 6346 6347 6348
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

B
Blue Swirl 已提交
6349
static void gen_lvsl(DisasContext *ctx)
A
aurel32 已提交
6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364
{
    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 已提交
6365
static void gen_lvsr(DisasContext *ctx)
A
aurel32 已提交
6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380
{
    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 已提交
6381
static void gen_mfvscr(DisasContext *ctx)
6382 6383 6384 6385 6386 6387 6388 6389 6390 6391
{
    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();
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, vscr));
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6392
    tcg_temp_free_i32(t);
6393 6394
}

B
Blue Swirl 已提交
6395
static void gen_mtvscr(DisasContext *ctx)
6396
{
A
aurel32 已提交
6397
    TCGv_ptr p;
6398 6399 6400 6401
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6402 6403 6404
    p = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_mtvscr(p);
    tcg_temp_free_ptr(p);
6405 6406
}

6407 6408
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
B
Blue Swirl 已提交
6409
static void glue(gen_, name)(DisasContext *ctx)                                 \
6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424
{                                                                       \
    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);

6425
#define GEN_VXFORM(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6426
static void glue(gen_, name)(DisasContext *ctx)                                 \
6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441
{                                                                       \
    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 已提交
6442 6443 6444 6445 6446 6447
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);
6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459
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 已提交
6460 6461 6462 6463 6464 6465
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 已提交
6466 6467 6468 6469 6470 6471
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 已提交
6472 6473 6474 6475 6476 6477 6478 6479
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 已提交
6480 6481 6482
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6483 6484 6485 6486 6487 6488
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 已提交
6489 6490
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6491 6492
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504
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 已提交
6505 6506 6507
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6508 6509
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6510 6511 6512 6513 6514 6515 6516 6517
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 已提交
6518
GEN_VXFORM(vpkpx, 7, 12);
6519 6520 6521 6522 6523
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);
6524 6525
GEN_VXFORM(vaddfp, 5, 0);
GEN_VXFORM(vsubfp, 5, 1);
6526 6527
GEN_VXFORM(vmaxfp, 5, 16);
GEN_VXFORM(vminfp, 5, 17);
A
aurel32 已提交
6528

6529
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
B
Blue Swirl 已提交
6530
static void glue(gen_, name)(DisasContext *ctx)                         \
6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549
    {                                                                   \
        TCGv_ptr ra, rb, rd;                                            \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        ra = gen_avr_ptr(rA(ctx->opcode));                              \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        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)))

6550 6551 6552 6553 6554 6555 6556 6557 6558
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)
6559 6560 6561 6562
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6563

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

6584
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
B
Blue Swirl 已提交
6585
static void glue(gen_, name)(DisasContext *ctx)                                 \
6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598
    {                                                                   \
        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 已提交
6599 6600 6601 6602
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 已提交
6603 6604
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
A
aurel32 已提交
6605
GEN_VXFORM_NOA(vrefp, 5, 4);
A
aurel32 已提交
6606
GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
6607
GEN_VXFORM_NOA(vexptefp, 5, 6);
6608
GEN_VXFORM_NOA(vlogefp, 5, 7);
A
aurel32 已提交
6609 6610 6611 6612
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 已提交
6613

6614
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6615
static void glue(gen_, name)(DisasContext *ctx)                                 \
6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629
    {                                                                   \
        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);                                          \
    }

6630
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6631
static void glue(gen_, name)(DisasContext *ctx)                                 \
6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647
    {                                                                   \
        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 已提交
6648 6649 6650
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
A
aurel32 已提交
6651 6652
GEN_VXFORM_UIMM(vcfux, 5, 12);
GEN_VXFORM_UIMM(vcfsx, 5, 13);
6653 6654
GEN_VXFORM_UIMM(vctuxs, 5, 14);
GEN_VXFORM_UIMM(vctsxs, 5, 15);
A
aurel32 已提交
6655

B
Blue Swirl 已提交
6656
static void gen_vsldoi(DisasContext *ctx)
A
aurel32 已提交
6657 6658
{
    TCGv_ptr ra, rb, rd;
6659
    TCGv_i32 sh;
A
aurel32 已提交
6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671
    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);
6672
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6673 6674
}

6675
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
B
Blue Swirl 已提交
6676
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                      \
6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697
    {                                                                   \
        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 已提交
6698 6699
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

B
Blue Swirl 已提交
6700
static void gen_vmladduhm(DisasContext *ctx)
A
aurel32 已提交
6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717
{
    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 已提交
6718
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6719
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6720
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6721
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6722
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6723

6724 6725
/***                           SPE extension                               ***/
/* Register moves */
6726

6727 6728 6729 6730 6731

static inline void gen_evmra(DisasContext *ctx)
{

    if (unlikely(!ctx->spe_enabled)) {
6732
        gen_exception(ctx, POWERPC_EXCP_SPEU);
6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759
        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,
                   offsetof(CPUState, spe_acc));
#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 */
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
    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 已提交
6760 6761
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
A
aurel32 已提交
6762 6763 6764
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
6765
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6766
#endif
A
aurel32 已提交
6767
}
6768

B
Blue Swirl 已提交
6769 6770
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
6771 6772 6773
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6774
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6775 6776 6777
    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 已提交
6778
    tcg_temp_free_i64(tmp);
6779
#endif
A
aurel32 已提交
6780
}
6781

6782
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type)         \
B
Blue Swirl 已提交
6783
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
6784 6785 6786 6787 6788 6789 6790 6791
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
6792
static inline void gen_speundef(DisasContext *ctx)
6793
{
A
aurel32 已提交
6794
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6795 6796
}

6797 6798 6799
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6800
static inline void gen_##name(DisasContext *ctx)                              \
6801 6802
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6803
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6804 6805
        return;                                                               \
    }                                                                         \
6806 6807 6808 6809 6810
    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 已提交
6811
static inline void gen_##name(DisasContext *ctx)                              \
6812 6813
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6814
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6815 6816 6817 6818 6819 6820
        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)]);                                        \
6821
}
6822 6823 6824 6825 6826 6827 6828 6829 6830 6831
#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);
6832

6833 6834 6835
/* SPE logic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6836
static inline void gen_##name(DisasContext *ctx)                              \
6837 6838
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6839
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6840 6841
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6842 6843 6844
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6845 6846 6847 6848
    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 已提交
6849
    tcg_temp_free_i64(t2);                                                    \
6850 6851
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6852 6853
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6854
}
6855 6856
#else
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6857
static inline void gen_##name(DisasContext *ctx)                              \
6858 6859
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6860
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6861 6862
        return;                                                               \
    }                                                                         \
6863 6864 6865 6866
    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));                                                 \
6867
}
6868 6869 6870 6871 6872
#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);
6873

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

B
Blue Swirl 已提交
6909
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
6910 6911 6912
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
6913

6914 6915 6916 6917
    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 已提交
6918
    tcg_gen_mov_i32(ret, arg1);
6919 6920 6921 6922 6923 6924
    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 已提交
6925
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
6926
{
6927 6928 6929 6930
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
6931 6932
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6933

6934 6935
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6936
static inline void gen_##name(DisasContext *ctx)                              \
6937 6938
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6939
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6940 6941
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6942 6943 6944
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
6945
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
6946 6947 6948 6949 6950 6951 6952
    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 已提交
6953
    tcg_temp_free_i64(t3);                                                    \
6954
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
6955
    tcg_temp_free_i32(t2);                                                    \
6956
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6957 6958
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6959
}
6960 6961
#else
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6962
static inline void gen_##name(DisasContext *ctx)                              \
6963 6964
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6965
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6966 6967
        return;                                                               \
    }                                                                         \
6968 6969 6970 6971
    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)]);                                        \
6972
}
6973
#endif
6974

B
Blue Swirl 已提交
6975
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6976
{
P
pbrook 已提交
6977
    TCGv_i32 t0;
6978
    int l1, l2;
6979

6980 6981
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6982
    t0 = tcg_temp_local_new_i32();
6983 6984 6985 6986 6987 6988 6989
    /* 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);
6990
    gen_set_label(l2);
P
pbrook 已提交
6991
    tcg_temp_free_i32(t0);
6992 6993
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
6994
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6995
{
P
pbrook 已提交
6996
    TCGv_i32 t0;
6997 6998 6999 7000
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7001
    t0 = tcg_temp_local_new_i32();
7002 7003 7004 7005 7006 7007 7008
    /* 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);
7009
    gen_set_label(l2);
P
pbrook 已提交
7010
    tcg_temp_free_i32(t0);
7011 7012
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
7013
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7014
{
P
pbrook 已提交
7015
    TCGv_i32 t0;
7016 7017 7018 7019
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7020
    t0 = tcg_temp_local_new_i32();
7021 7022 7023 7024 7025 7026 7027
    /* 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);
7028
    gen_set_label(l2);
P
pbrook 已提交
7029
    tcg_temp_free_i32(t0);
7030 7031
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
B
Blue Swirl 已提交
7032
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7033
{
P
pbrook 已提交
7034
    TCGv_i32 t0 = tcg_temp_new_i32();
7035 7036
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
7037
    tcg_temp_free_i32(t0);
7038 7039
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
B
Blue Swirl 已提交
7040
static inline void gen_evmergehi(DisasContext *ctx)
7041 7042
{
    if (unlikely(!ctx->spe_enabled)) {
7043
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7044 7045 7046
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7047 7048
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059
    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 已提交
7060
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7061
{
7062 7063 7064
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
7065

7066 7067 7068
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7069
static inline void gen_##name(DisasContext *ctx)                              \
7070 7071
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7072
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7073 7074
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7075 7076 7077
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7078 7079 7080 7081
    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 已提交
7082
    tcg_temp_free_i64(t2);                                                    \
7083 7084
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7085 7086
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7087 7088 7089
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7090
static inline void gen_##name(DisasContext *ctx)                              \
7091 7092
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7093
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107
        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 已提交
7108
static inline void gen_##name(DisasContext *ctx)                              \
7109 7110
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7111
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7112 7113 7114 7115 7116 7117
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
7118 7119 7120
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7121 7122 7123
    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 已提交
7124
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
7125 7126 7127 7128 7129 7130 7131 7132 7133
    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 已提交
7134
    tcg_temp_free_i64(t2);                                                    \
7135 7136 7137 7138 7139 7140 7141 7142
    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 已提交
7143 7144
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7145 7146 7147
}
#else
#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 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184
        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 已提交
7185
static inline void gen_brinc(DisasContext *ctx)
7186 7187
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
7188 7189
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7190
}
B
Blue Swirl 已提交
7191
static inline void gen_evmergelo(DisasContext *ctx)
7192 7193
{
    if (unlikely(!ctx->spe_enabled)) {
7194
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7195 7196 7197
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7198 7199
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7200
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7201 7202 7203 7204 7205 7206
    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)]);
7207
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7208 7209
#endif
}
B
Blue Swirl 已提交
7210
static inline void gen_evmergehilo(DisasContext *ctx)
7211 7212
{
    if (unlikely(!ctx->spe_enabled)) {
7213
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7214 7215 7216
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7217 7218
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7219
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7220 7221 7222 7223 7224 7225 7226 7227 7228
    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 已提交
7229
static inline void gen_evmergelohi(DisasContext *ctx)
7230 7231
{
    if (unlikely(!ctx->spe_enabled)) {
7232
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7233 7234 7235
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7236 7237
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7238 7239 7240 7241 7242 7243
    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
7244 7245 7246 7247 7248 7249 7250 7251 7252 7253
    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)]);
    }
7254 7255
#endif
}
B
Blue Swirl 已提交
7256
static inline void gen_evsplati(DisasContext *ctx)
7257
{
7258
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
7259

7260
#if defined(TARGET_PPC64)
7261
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7262 7263 7264 7265 7266
#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 已提交
7267
static inline void gen_evsplatfi(DisasContext *ctx)
7268
{
7269
    uint64_t imm = rA(ctx->opcode) << 27;
7270

7271
#if defined(TARGET_PPC64)
7272
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7273 7274 7275 7276
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7277 7278
}

B
Blue Swirl 已提交
7279
static inline void gen_evsel(DisasContext *ctx)
7280 7281 7282 7283 7284
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7285
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7286
#if defined(TARGET_PPC64)
P
pbrook 已提交
7287 7288
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307
#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)
7308
    tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
7309 7310 7311 7312 7313 7314
#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)
7315
    tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
7316 7317 7318 7319
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7320
    tcg_temp_free_i32(t0);
7321 7322 7323 7324 7325 7326
#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 已提交
7327 7328

static void gen_evsel0(DisasContext *ctx)
7329 7330 7331
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7332 7333

static void gen_evsel1(DisasContext *ctx)
7334 7335 7336
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7337 7338

static void gen_evsel2(DisasContext *ctx)
7339 7340 7341
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7342 7343

static void gen_evsel3(DisasContext *ctx)
7344 7345 7346
{
    gen_evsel(ctx);
}
7347

7348 7349 7350 7351 7352 7353 7354
/* Multiply */

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

    if (unlikely(!ctx->spe_enabled)) {
7355
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383
        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)) {
7384
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403
        return;
    }

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

    tmp = tcg_temp_new_i64();

    /* acc := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
    tcg_temp_free_i64(tmp);
}

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

    if (unlikely(!ctx->spe_enabled)) {
7404
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436
        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 */
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));

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

    /* Store acc */
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUState, spe_acc));

    /* 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)) {
7437
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504
        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));
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));

    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 */
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));

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

    /* Store acc */
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUState, spe_acc));

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

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533
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); ////
7534

7535
/* SPE load and stores */
B
Blue Swirl 已提交
7536
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7537 7538 7539
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7540
    if (rA(ctx->opcode) == 0) {
7541
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7542
    } else {
7543
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
A
aurel32 已提交
7544 7545 7546 7547 7548 7549
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
7550
}
7551

B
Blue Swirl 已提交
7552
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7553 7554
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7555
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7556 7557
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7558
    gen_qemu_ld64(ctx, t0, addr);
7559 7560 7561 7562 7563
    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
7564
}
7565

B
Blue Swirl 已提交
7566
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7567
{
7568
#if defined(TARGET_PPC64)
7569
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7570
    gen_qemu_ld32u(ctx, t0, addr);
7571
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7572 7573
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7574 7575 7576
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7577 7578 7579
    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);
7580
#endif
7581
}
7582

B
Blue Swirl 已提交
7583
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7584 7585 7586
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7587
    gen_qemu_ld16u(ctx, t0, addr);
7588
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7589 7590
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7591 7592
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7593 7594
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7595 7596
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7597 7598
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7599
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7600
#else
A
aurel32 已提交
7601
    gen_qemu_ld16u(ctx, t0, addr);
7602
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7603 7604
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7605
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7606 7607
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7608
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7609 7610
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7611
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7612
#endif
7613
    tcg_temp_free(t0);
7614 7615
}

B
Blue Swirl 已提交
7616
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7617 7618
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7619
    gen_qemu_ld16u(ctx, t0, addr);
7620 7621 7622 7623 7624 7625 7626 7627 7628 7629
#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);
7630 7631
}

B
Blue Swirl 已提交
7632
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7633 7634
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7635
    gen_qemu_ld16u(ctx, t0, addr);
7636 7637 7638 7639 7640 7641 7642 7643
#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);
7644 7645
}

B
Blue Swirl 已提交
7646
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7647 7648
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7649
    gen_qemu_ld16s(ctx, t0, addr);
7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660
#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 已提交
7661
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7662 7663 7664
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7665
    gen_qemu_ld16u(ctx, t0, addr);
7666
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7667 7668
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7669 7670 7671
    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 已提交
7672
    gen_qemu_ld16u(ctx, t0, addr);
7673
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7674 7675
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7676 7677 7678 7679 7680
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7681
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7682 7683 7684
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7685 7686 7687
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7688 7689 7690 7691
    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 已提交
7692 7693 7694
    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);
7695 7696 7697
#endif
}

B
Blue Swirl 已提交
7698
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7699 7700 7701
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7702
    gen_qemu_ld16s(ctx, t0, addr);
7703
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7704 7705
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7706 7707 7708 7709
    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 已提交
7710 7711 7712
    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);
7713 7714 7715
#endif
}

B
Blue Swirl 已提交
7716
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7717 7718
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7719
    gen_qemu_ld32u(ctx, t0, addr);
7720
#if defined(TARGET_PPC64)
7721 7722 7723 7724 7725 7726 7727 7728 7729
    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 已提交
7730
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7731 7732 7733
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7734
    gen_qemu_ld16u(ctx, t0, addr);
7735 7736 7737
    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 已提交
7738 7739
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7740 7741 7742 7743
    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 已提交
7744
    gen_qemu_ld16u(ctx, t0, addr);
7745 7746
    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 已提交
7747 7748
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7749 7750
    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);
7751
#endif
7752 7753 7754
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7755
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7756 7757
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7758
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7759
#else
7760 7761
    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 已提交
7762
    gen_qemu_st64(ctx, t0, addr);
7763 7764 7765 7766
    tcg_temp_free_i64(t0);
#endif
}

B
Blue Swirl 已提交
7767
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7768
{
7769
#if defined(TARGET_PPC64)
7770 7771
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7772
    gen_qemu_st32(ctx, t0, addr);
7773 7774
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7775
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7776
#endif
A
aurel32 已提交
7777 7778
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7779 7780
}

B
Blue Swirl 已提交
7781
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7782 7783 7784 7785 7786 7787 7788
{
    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 已提交
7789 7790
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7791 7792
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7793
    gen_qemu_st16(ctx, t0, addr);
7794
#else
A
aurel32 已提交
7795
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7796
#endif
A
aurel32 已提交
7797
    gen_addr_add(ctx, addr, addr, 2);
7798
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7799
    gen_qemu_st16(ctx, t0, addr);
7800
    tcg_temp_free(t0);
A
aurel32 已提交
7801 7802
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7803 7804
}

B
Blue Swirl 已提交
7805
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7806 7807 7808 7809 7810 7811 7812
{
    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 已提交
7813 7814
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7815
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7816
    gen_qemu_st16(ctx, t0, addr);
7817 7818 7819
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7820
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7821 7822 7823 7824
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7825
    gen_qemu_st16(ctx, t0, addr);
7826 7827
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7828
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7829
#endif
A
aurel32 已提交
7830 7831
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7832 7833
}

B
Blue Swirl 已提交
7834
static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7835 7836 7837 7838
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7839
    gen_qemu_st32(ctx, t0, addr);
7840 7841
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7842
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7843 7844 7845
#endif
}

B
Blue Swirl 已提交
7846
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7847
{
A
aurel32 已提交
7848
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7849 7850 7851
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
B
Blue Swirl 已提交
7852
static void glue(gen_, name)(DisasContext *ctx)                                       \
7853 7854 7855
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7856
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7857 7858
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7859
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7860 7861
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
7862
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7863
    } else {                                                                  \
A
aurel32 已提交
7864
        gen_addr_reg_index(ctx, t0);                                          \
7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888
    }                                                                         \
    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);
7889 7890 7891

/* Multiply and add - TODO */
#if 0
7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959
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);
7960 7961 7962
#endif

/***                      SPE floating-point extension                     ***/
A
aurel32 已提交
7963 7964
#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
7965
static inline void gen_##name(DisasContext *ctx)                              \
7966
{                                                                             \
A
aurel32 已提交
7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978
    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);                                                        \
7979
}
A
aurel32 已提交
7980
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
7981
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995
{                                                                             \
    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 已提交
7996
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7997 7998 7999 8000 8001 8002 8003
{                                                                             \
    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 已提交
8004
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8005 8006 8007 8008
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
8009
static inline void gen_##name(DisasContext *ctx)                              \
8010
{                                                                             \
A
aurel32 已提交
8011 8012
    TCGv_i32 t0, t1;                                                          \
    TCGv_i64 t2;                                                              \
8013
    if (unlikely(!ctx->spe_enabled)) {                                        \
8014
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8015 8016
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029
    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);                                                        \
8030
}
A
aurel32 已提交
8031
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
8032
static inline void gen_##name(DisasContext *ctx)                              \
8033 8034
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8035
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8036 8037
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8038 8039
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],     \
                      cpu_gpr[rB(ctx->opcode)]);                              \
8040
}
A
aurel32 已提交
8041
#define GEN_SPEFPUOP_COMP_32(name)                                            \
B
Blue Swirl 已提交
8042
static inline void gen_##name(DisasContext *ctx)                              \
8043
{                                                                             \
A
aurel32 已提交
8044
    TCGv_i32 t0, t1;                                                          \
8045
    if (unlikely(!ctx->spe_enabled)) {                                        \
8046
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8047 8048
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8049 8050 8051 8052 8053 8054 8055 8056 8057
    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 已提交
8058
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8059 8060
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8061
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8062 8063 8064 8065 8066 8067 8068
        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 已提交
8069
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8070 8071
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
8072
}
A
aurel32 已提交
8073
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
8074
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8075 8076 8077 8078 8079 8080 8081
{                                                                             \
    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 已提交
8082
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8083 8084 8085 8086 8087 8088 8089
{                                                                             \
    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 已提交
8090
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8091 8092 8093 8094 8095 8096 8097 8098
{                                                                             \
    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 已提交
8099
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8100 8101
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8102
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8103 8104 8105 8106 8107 8108
        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 已提交
8109
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8110 8111 8112
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8113
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125
        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 已提交
8126
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8127 8128
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8129
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8130 8131 8132 8133 8134 8135
        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 已提交
8136
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8137 8138 8139
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8140
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151
        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
8152

8153 8154
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
8155 8156 8157 8158
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 已提交
8159
static inline void gen_evfsabs(DisasContext *ctx)
A
aurel32 已提交
8160 8161
{
    if (unlikely(!ctx->spe_enabled)) {
8162
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8163 8164 8165
        return;
    }
#if defined(TARGET_PPC64)
8166
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
A
aurel32 已提交
8167
#else
8168 8169
    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 已提交
8170 8171
#endif
}
B
Blue Swirl 已提交
8172
static inline void gen_evfsnabs(DisasContext *ctx)
A
aurel32 已提交
8173 8174
{
    if (unlikely(!ctx->spe_enabled)) {
8175
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8176 8177 8178
        return;
    }
#if defined(TARGET_PPC64)
8179
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8180
#else
8181 8182
    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 已提交
8183 8184
#endif
}
B
Blue Swirl 已提交
8185
static inline void gen_evfsneg(DisasContext *ctx)
A
aurel32 已提交
8186 8187
{
    if (unlikely(!ctx->spe_enabled)) {
8188
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8189 8190 8191
        return;
    }
#if defined(TARGET_PPC64)
8192
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8193
#else
8194 8195
    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 已提交
8196 8197 8198
#endif
}

8199
/* Conversion */
A
aurel32 已提交
8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210
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);

8211
/* Comparison */
A
aurel32 已提交
8212 8213 8214 8215 8216 8217
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);
8218 8219

/* Opcodes definitions */
8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233
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); //
8234 8235 8236

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8237 8238 8239 8240
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 已提交
8241
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
8242 8243
{
    if (unlikely(!ctx->spe_enabled)) {
8244
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8245 8246
        return;
    }
8247
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
A
aurel32 已提交
8248
}
B
Blue Swirl 已提交
8249
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
8250 8251
{
    if (unlikely(!ctx->spe_enabled)) {
8252
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8253 8254
        return;
    }
8255
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8256
}
B
Blue Swirl 已提交
8257
static inline void gen_efsneg(DisasContext *ctx)
A
aurel32 已提交
8258 8259
{
    if (unlikely(!ctx->spe_enabled)) {
8260
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8261 8262
        return;
    }
8263
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8264 8265
}

8266
/* Conversion */
A
aurel32 已提交
8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278
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);

8279
/* Comparison */
A
aurel32 已提交
8280 8281 8282 8283 8284 8285
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);
8286 8287

/* Opcodes definitions */
8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301
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); //
8302 8303 8304

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8305 8306 8307 8308
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 已提交
8309
static inline void gen_efdabs(DisasContext *ctx)
A
aurel32 已提交
8310 8311
{
    if (unlikely(!ctx->spe_enabled)) {
8312
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8313 8314 8315
        return;
    }
#if defined(TARGET_PPC64)
8316
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
A
aurel32 已提交
8317
#else
8318 8319
    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 已提交
8320 8321
#endif
}
B
Blue Swirl 已提交
8322
static inline void gen_efdnabs(DisasContext *ctx)
A
aurel32 已提交
8323 8324
{
    if (unlikely(!ctx->spe_enabled)) {
8325
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8326 8327 8328
        return;
    }
#if defined(TARGET_PPC64)
8329
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8330
#else
8331 8332
    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 已提交
8333 8334
#endif
}
B
Blue Swirl 已提交
8335
static inline void gen_efdneg(DisasContext *ctx)
A
aurel32 已提交
8336 8337
{
    if (unlikely(!ctx->spe_enabled)) {
8338
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8339 8340 8341
        return;
    }
#if defined(TARGET_PPC64)
8342
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8343
#else
8344 8345
    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 已提交
8346 8347 8348
#endif
}

8349
/* Conversion */
A
aurel32 已提交
8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364
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);
8365 8366

/* Comparison */
A
aurel32 已提交
8367 8368 8369 8370 8371 8372
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);
8373 8374

/* Opcodes definitions */
8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390
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); //
8391

A
Anthony Liguori 已提交
8392
static opcode_t opcodes[] = {
8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423
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),
8424
GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
8425
#if defined(TARGET_PPC64)
8426
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467
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),
8468
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
8469 8470
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
8471
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
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 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526
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),
8527 8528 8529
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),
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 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609
#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 已提交
8610
GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
8611 8612 8613 8614 8615 8616 8617 8618
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 已提交
8619 8620 8621 8622 8623 8624 8625 8626
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 已提交
8627 8628
GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8629 8630
GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
8631
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8632
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8633
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
A
Alexander Graf 已提交
8634 8635
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
              PPC_BOOKE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8636
GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
A
Alexander Graf 已提交
8637 8638
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
               PPC_BOOKE, PPC2_BOOKE206),
8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 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
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
#undef GEN_LDX
#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),
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
#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)
#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
#undef GEN_STX
#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),
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
#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)
#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),
9133
GEN_VXFORM_NOA(vexptefp, 5, 6),
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
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
9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239
#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),
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

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

9265
#include "translate_init.c"
9266
#include "helper_regs.h"
B
bellard 已提交
9267

9268
/*****************************************************************************/
9269
/* Misc PowerPC helpers */
9270
void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
9271
                     int flags)
B
bellard 已提交
9272
{
9273 9274 9275
#define RGPL  4
#define RFPL  4

B
bellard 已提交
9276 9277
    int i;

9278
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
9279 9280
                TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
                env->nip, env->lr, env->ctr, env->xer);
9281 9282 9283
    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);
9284
#if !defined(NO_TIMER_DUMP)
9285
    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
9286
#if !defined(CONFIG_USER_ONLY)
9287
                " DECR %08" PRIu32
9288 9289
#endif
                "\n",
J
j_mayer 已提交
9290
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
9291 9292 9293 9294
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
9295
#endif
9296
    for (i = 0; i < 32; i++) {
9297 9298
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
9299
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
9300
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
9301
            cpu_fprintf(f, "\n");
9302
    }
9303
    cpu_fprintf(f, "CR ");
9304
    for (i = 0; i < 8; i++)
B
bellard 已提交
9305 9306
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
9307 9308 9309 9310 9311 9312 9313 9314
    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 已提交
9315
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
9316
    }
9317 9318
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
9319 9320 9321
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
9322
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
9323
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
9324
            cpu_fprintf(f, "\n");
B
bellard 已提交
9325
    }
9326
    cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
9327
#if !defined(CONFIG_USER_ONLY)
S
Scott Wood 已提交
9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375
    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 已提交
9376 9377 9378 9379 9380 9381
#if defined(TARGET_PPC64)
    if (env->flags & POWERPC_FLAG_CFAR) {
        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
    }
#endif

S
Scott Wood 已提交
9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392
    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 已提交
9393
    case POWERPC_MMU_BOOKE206:
S
Scott Wood 已提交
9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411
        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;
    }
9412
#endif
B
bellard 已提交
9413

9414 9415
#undef RGPL
#undef RFPL
B
bellard 已提交
9416 9417
}

9418
void cpu_dump_statistics (CPUState *env, FILE*f, fprintf_function cpu_fprintf,
9419 9420 9421
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
A
Anthony Liguori 已提交
9422
    opc_handler_t **t1, **t2, **t3, *handler;
9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438
    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 已提交
9439
                                    "%016" PRIx64 " %" PRId64 "\n",
9440 9441 9442 9443 9444 9445 9446 9447
                                    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 已提交
9448
                                "%016" PRIx64 " %" PRId64 "\n",
9449 9450 9451 9452 9453 9454 9455
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
B
Blue Swirl 已提交
9456 9457
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
                        " %" PRId64 "\n",
9458 9459 9460 9461 9462 9463 9464
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

9465
/*****************************************************************************/
B
Blue Swirl 已提交
9466 9467 9468
static inline void gen_intermediate_code_internal(CPUState *env,
                                                  TranslationBlock *tb,
                                                  int search_pc)
B
bellard 已提交
9469
{
9470
    DisasContext ctx, *ctxp = &ctx;
A
Anthony Liguori 已提交
9471
    opc_handler_t **table, *handler;
B
bellard 已提交
9472
    target_ulong pc_start;
B
bellard 已提交
9473
    uint16_t *gen_opc_end;
9474
    CPUBreakpoint *bp;
B
bellard 已提交
9475
    int j, lj = -1;
P
pbrook 已提交
9476 9477
    int num_insns;
    int max_insns;
B
bellard 已提交
9478 9479 9480

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
9481
    ctx.nip = pc_start;
B
bellard 已提交
9482
    ctx.tb = tb;
9483
    ctx.exception = POWERPC_EXCP_NONE;
9484
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
9485 9486 9487
    ctx.mem_idx = env->mmu_idx;
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
9488 9489
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
D
David Gibson 已提交
9490
    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9491
#endif
B
bellard 已提交
9492
    ctx.fpu_enabled = msr_fp;
9493
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
9494 9495 9496
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
9497 9498 9499 9500
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
9501
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
9502
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
9503
    else
9504
        ctx.singlestep_enabled = 0;
9505
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
9506 9507 9508
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
9509
#if defined (DO_SINGLE_STEP) && 0
9510 9511 9512
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
9513 9514 9515 9516 9517 9518
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
9519
    /* Set env in case of segfault during code fetch */
9520
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
B
Blue Swirl 已提交
9521 9522
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9523
                if (bp->pc == ctx.nip) {
A
aurel32 已提交
9524
                    gen_debug_exception(ctxp);
9525 9526 9527 9528
                    break;
                }
            }
        }
9529
        if (unlikely(search_pc)) {
B
bellard 已提交
9530 9531 9532 9533 9534 9535
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
            }
9536 9537 9538
            gen_opc_pc[lj] = ctx.nip;
            gen_opc_instr_start[lj] = 1;
            gen_opc_icount[lj] = num_insns;
B
bellard 已提交
9539
        }
9540
        LOG_DISAS("----------------\n");
9541
        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
9542
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
P
pbrook 已提交
9543 9544
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
A
aurel32 已提交
9545
        if (unlikely(ctx.le_mode)) {
9546 9547 9548
            ctx.opcode = bswap32(ldl_code(ctx.nip));
        } else {
            ctx.opcode = ldl_code(ctx.nip);
9549
        }
9550
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9551
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
9552
                    opc3(ctx.opcode), little_endian ? "little" : "big");
9553 9554
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
            tcg_gen_debug_insn_start(ctx.nip);
B
bellard 已提交
9555
        ctx.nip += 4;
9556
        table = env->opcodes;
P
pbrook 已提交
9557
        num_insns++;
B
bellard 已提交
9558 9559 9560 9561 9562 9563 9564 9565 9566 9567
        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 ? */
9568
        if (unlikely(handler->handler == &gen_invalid)) {
9569 9570
            if (qemu_log_enabled()) {
                qemu_log("invalid/unsupported opcode: "
9571 9572 9573
                         "%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 已提交
9574
            }
9575
        } else {
9576 9577 9578 9579 9580 9581 9582 9583 9584
            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)) {
9585 9586
                if (qemu_log_enabled()) {
                    qemu_log("invalid bits: %08x for opcode: "
9587
                             "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
9588
                             ctx.opcode & inval, opc1(ctx.opcode),
9589 9590
                             opc2(ctx.opcode), opc3(ctx.opcode),
                             ctx.opcode, ctx.nip - 4);
9591
                }
A
aurel32 已提交
9592
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
B
bellard 已提交
9593
                break;
B
bellard 已提交
9594 9595
            }
        }
B
bellard 已提交
9596
        (*(handler->handler))(&ctx);
9597 9598 9599
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
9600
        /* Check trace mode exceptions */
9601 9602 9603 9604 9605
        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 已提交
9606
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
9607
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
9608
                            (env->singlestep_enabled) ||
9609
                            singlestep ||
P
pbrook 已提交
9610
                            num_insns >= max_insns)) {
9611 9612 9613
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
9614
            break;
9615
        }
9616
    }
P
pbrook 已提交
9617 9618
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
9619
    if (ctx.exception == POWERPC_EXCP_NONE) {
9620
        gen_goto_tb(&ctx, 0, ctx.nip);
9621
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
9622
        if (unlikely(env->singlestep_enabled)) {
A
aurel32 已提交
9623
            gen_debug_exception(ctxp);
9624
        }
9625
        /* Generate the return instruction */
B
bellard 已提交
9626
        tcg_gen_exit_tb(0);
9627
    }
P
pbrook 已提交
9628
    gen_icount_end(tb, num_insns);
B
bellard 已提交
9629
    *gen_opc_ptr = INDEX_op_end;
9630
    if (unlikely(search_pc)) {
9631 9632 9633 9634 9635
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
B
bellard 已提交
9636
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
9637
        tb->icount = num_insns;
9638
    }
9639
#if defined(DEBUG_DISAS)
9640
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9641
        int flags;
9642
        flags = env->bfd_mach;
A
aurel32 已提交
9643
        flags |= ctx.le_mode << 16;
9644 9645 9646
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
        log_target_disas(pc_start, ctx.nip - pc_start, flags);
        qemu_log("\n");
9647
    }
B
bellard 已提交
9648 9649 9650
#endif
}

9651
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
9652
{
9653
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
9654 9655
}

9656
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
9657
{
9658
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
9659
}
A
aurel32 已提交
9660

9661
void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
A
aurel32 已提交
9662 9663 9664
{
    env->nip = gen_opc_pc[pc_pos];
}