translate.c 334.8 KB
Newer Older
B
bellard 已提交
1
/*
2
 *  PowerPC emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
B
bellard 已提交
5 6 7 8 9 10 11 12 13 14 15 16
 *
 * 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
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
B
bellard 已提交
18
 */
B
bellard 已提交
19 20 21 22 23 24
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

B
bellard 已提交
25
#include "cpu.h"
B
bellard 已提交
26
#include "exec-all.h"
B
bellard 已提交
27
#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;
A
aurel32 已提交
72
static TCGv cpu_xer;
73
static TCGv cpu_reserve;
P
pbrook 已提交
74
static TCGv_i32 cpu_fpscr;
A
aurel32 已提交
75
static TCGv_i32 cpu_access_type;
A
aurel32 已提交
76

P
pbrook 已提交
77 78 79 80
#include "gen-icount.h"

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

P
pbrook 已提交
86 87
    if (done_init)
        return;
A
aurel32 已提交
88

P
pbrook 已提交
89 90
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");

A
aurel32 已提交
91
    p = cpu_reg_names;
92
    cpu_reg_names_size = sizeof(cpu_reg_names);
A
aurel32 已提交
93 94

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

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

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

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

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

P
pbrook 已提交
145
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
146 147
                                 offsetof(CPUState, nip), "nip");

148 149 150
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
                                 offsetof(CPUState, msr), "msr");

P
pbrook 已提交
151
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
152 153
                                 offsetof(CPUState, ctr), "ctr");

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

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

160
    cpu_reserve = tcg_global_mem_new(TCG_AREG0,
161 162
                                     offsetof(CPUState, reserve_addr),
                                     "reserve_addr");
163

P
pbrook 已提交
164 165
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
                                       offsetof(CPUState, fpscr), "fpscr");
166

A
aurel32 已提交
167 168 169
    cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
                                             offsetof(CPUState, access_type), "access_type");

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

P
pbrook 已提交
174 175 176
    done_init = 1;
}

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

A
Anthony Liguori 已提交
198
struct opc_handler_t {
B
bellard 已提交
199 200
    /* invalid bits */
    uint32_t inval;
201
    /* instruction type */
202
    uint64_t type;
B
bellard 已提交
203 204
    /* handler */
    void (*handler)(DisasContext *ctx);
205
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
206
    const char *oname;
207 208
#endif
#if defined(DO_PPC_STATISTICS)
209 210
    uint64_t count;
#endif
211
};
B
bellard 已提交
212

B
Blue Swirl 已提交
213
static inline void gen_reset_fpstatus(void)
214 215
{
#ifdef CONFIG_SOFTFLOAT
216
    gen_helper_reset_fpstatus();
217 218 219
#endif
}

B
Blue Swirl 已提交
220
static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
221
{
222
    TCGv_i32 t0 = tcg_temp_new_i32();
A
aurel32 已提交
223

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

239
    tcg_temp_free_i32(t0);
240 241
}

B
Blue Swirl 已提交
242
static inline void gen_set_access_type(DisasContext *ctx, int access_type)
A
aurel32 已提交
243
{
A
aurel32 已提交
244 245 246 247
    if (ctx->access_type != access_type) {
        tcg_gen_movi_i32(cpu_access_type, access_type);
        ctx->access_type = access_type;
    }
A
aurel32 已提交
248 249
}

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

B
Blue Swirl 已提交
260
static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
A
aurel32 已提交
261 262 263 264 265 266 267 268 269 270 271 272
{
    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);
}
273

B
Blue Swirl 已提交
274
static inline void gen_exception(DisasContext *ctx, uint32_t excp)
A
aurel32 已提交
275 276 277 278 279 280 281 282 283 284
{
    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);
}
285

B
Blue Swirl 已提交
286
static inline void gen_debug_exception(DisasContext *ctx)
A
aurel32 已提交
287 288
{
    TCGv_i32 t0;
B
blueswir1 已提交
289 290 291

    if (ctx->exception != POWERPC_EXCP_BRANCH)
        gen_update_nip(ctx, ctx->nip);
A
aurel32 已提交
292 293 294 295
    t0 = tcg_const_i32(EXCP_DEBUG);
    gen_helper_raise_exception(t0);
    tcg_temp_free_i32(t0);
}
296

B
Blue Swirl 已提交
297
static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
A
aurel32 已提交
298 299 300
{
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
}
301

302
/* Stop translation */
B
Blue Swirl 已提交
303
static inline void gen_stop_exception(DisasContext *ctx)
304
{
305
    gen_update_nip(ctx, ctx->nip);
306
    ctx->exception = POWERPC_EXCP_STOP;
307 308
}

309
/* No need to update nip here, as execution flow will change */
B
Blue Swirl 已提交
310
static inline void gen_sync_exception(DisasContext *ctx)
311
{
312
    ctx->exception = POWERPC_EXCP_SYNC;
313 314
}

B
bellard 已提交
315
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
316
GEN_OPCODE(name, opc1, opc2, opc3, inval, type)
B
bellard 已提交
317

318
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
319
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type)
320

A
Anthony Liguori 已提交
321
typedef struct opcode_t {
B
bellard 已提交
322
    unsigned char opc1, opc2, opc3;
T
ths 已提交
323
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
324 325 326 327
    unsigned char pad[5];
#else
    unsigned char pad[1];
#endif
A
Anthony Liguori 已提交
328
    opc_handler_t handler;
329
    const char *oname;
A
Anthony Liguori 已提交
330
} opcode_t;
B
bellard 已提交
331

332
/*****************************************************************************/
B
bellard 已提交
333 334
/***                           Instruction decoding                        ***/
#define EXTRACT_HELPER(name, shift, nb)                                       \
B
Blue Swirl 已提交
335
static inline uint32_t name(uint32_t opcode)                                  \
B
bellard 已提交
336 337 338 339 340
{                                                                             \
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
}

#define EXTRACT_SHELPER(name, shift, nb)                                      \
B
Blue Swirl 已提交
341
static inline int32_t name(uint32_t opcode)                                   \
B
bellard 已提交
342
{                                                                             \
343
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
B
bellard 已提交
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
}

/* 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 */
371
EXTRACT_HELPER(_SPR, 11, 10);
B
Blue Swirl 已提交
372
static inline uint32_t SPR(uint32_t opcode)
373 374 375 376 377
{
    uint32_t sprn = _SPR(opcode);

    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
}
B
bellard 已提交
378 379 380 381 382 383
/***                              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);
384 385
/* 5 bits signed immediate value */
EXTRACT_HELPER(SIMM5, 16, 5);
386 387
/* 5 bits signed immediate value */
EXTRACT_HELPER(UIMM5, 16, 5);
B
bellard 已提交
388 389 390 391
/* Bit count */
EXTRACT_HELPER(NB, 11, 5);
/* Shift count */
EXTRACT_HELPER(SH, 11, 5);
A
aurel32 已提交
392 393
/* Vector shift count */
EXTRACT_HELPER(VSH, 6, 4);
B
bellard 已提交
394 395 396 397
/* Mask start */
EXTRACT_HELPER(MB, 6, 5);
/* Mask end */
EXTRACT_HELPER(ME, 1, 5);
B
bellard 已提交
398 399
/* Trap operand */
EXTRACT_HELPER(TO, 21, 5);
B
bellard 已提交
400 401 402 403

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

B
bellard 已提交
406 407 408 409
/***                            Jump target decoding                       ***/
/* Displacement */
EXTRACT_SHELPER(d, 0, 16);
/* Immediate address */
B
Blue Swirl 已提交
410
static inline target_ulong LI(uint32_t opcode)
B
bellard 已提交
411 412 413 414
{
    return (opcode >> 0) & 0x03FFFFFC;
}

B
Blue Swirl 已提交
415
static inline uint32_t BD(uint32_t opcode)
B
bellard 已提交
416 417 418 419 420 421 422 423 424 425 426 427
{
    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 已提交
428
static inline target_ulong MASK(uint32_t start, uint32_t end)
B
bellard 已提交
429
{
430
    target_ulong ret;
B
bellard 已提交
431

432 433
#if defined(TARGET_PPC64)
    if (likely(start == 0)) {
434
        ret = UINT64_MAX << (63 - end);
435
    } else if (likely(end == 63)) {
436
        ret = UINT64_MAX >> start;
437 438 439
    }
#else
    if (likely(start == 0)) {
440
        ret = UINT32_MAX << (31  - end);
441
    } else if (likely(end == 31)) {
442
        ret = UINT32_MAX >> start;
443 444 445 446 447 448 449 450
    }
#endif
    else {
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
            (((target_ulong)(-1ULL) >> (end)) >> 1);
        if (unlikely(start > end))
            return ~ret;
    }
B
bellard 已提交
451 452 453 454

    return ret;
}

455 456
/*****************************************************************************/
/* PowerPC instructions table                                                */
B
bellard 已提交
457

458
#if defined(DO_PPC_STATISTICS)
B
bellard 已提交
459
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
460
{                                                                             \
B
bellard 已提交
461 462 463
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
464
    .pad  = { 0, },                                                           \
B
bellard 已提交
465 466
    .handler = {                                                              \
        .inval   = invl,                                                      \
467
        .type = _typ,                                                         \
B
bellard 已提交
468
        .handler = &gen_##name,                                               \
469
        .oname = stringify(name),                                             \
B
bellard 已提交
470
    },                                                                        \
471
    .oname = stringify(name),                                                 \
B
bellard 已提交
472
}
473
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
474
{                                                                             \
475 476 477 478 479 480 481 482 483 484 485 486
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval   = invl,                                                      \
        .type = _typ,                                                         \
        .handler = &gen_##name,                                               \
        .oname = onam,                                                        \
    },                                                                        \
    .oname = onam,                                                            \
}
487 488
#else
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
489
{                                                                             \
490 491 492 493 494 495 496 497
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval   = invl,                                                      \
        .type = _typ,                                                         \
        .handler = &gen_##name,                                               \
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
    },                                                                        \
    .oname = stringify(name),                                                 \
}
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval   = invl,                                                      \
        .type = _typ,                                                         \
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = onam,                                                            \
}
#endif
515

516
/* SPR load/store helpers */
B
Blue Swirl 已提交
517
static inline void gen_load_spr(TCGv t, int reg)
518 519 520
{
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
}
521

B
Blue Swirl 已提交
522
static inline void gen_store_spr(int reg, TCGv t)
523 524 525
{
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
}
526

527
/* Invalid instruction */
B
Blue Swirl 已提交
528
static void gen_invalid(DisasContext *ctx)
529
{
A
aurel32 已提交
530
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
531 532
}

A
Anthony Liguori 已提交
533
static opc_handler_t invalid_handler = {
B
bellard 已提交
534
    .inval   = 0xFFFFFFFF,
535
    .type    = PPC_NONE,
B
bellard 已提交
536 537 538
    .handler = gen_invalid,
};

539 540
/***                           Integer comparison                          ***/

B
Blue Swirl 已提交
541
static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
542 543 544
{
    int l1, l2, l3;

545 546
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
547 548 549 550 551 552
    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) {
553 554
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
555
    } else {
556 557
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
558 559 560 561 562 563 564 565 566 567 568
    }
    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 已提交
569
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
570
{
571 572 573
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
574 575 576
}

#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
577
static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
578
{
579
    TCGv t0, t1;
P
pbrook 已提交
580 581
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
582
    if (s) {
583 584
        tcg_gen_ext32s_tl(t0, arg0);
        tcg_gen_ext32s_tl(t1, arg1);
585
    } else {
586 587
        tcg_gen_ext32u_tl(t0, arg0);
        tcg_gen_ext32u_tl(t1, arg1);
588
    }
589 590 591
    gen_op_cmp(t0, t1, s, crf);
    tcg_temp_free(t1);
    tcg_temp_free(t0);
592 593
}

B
Blue Swirl 已提交
594
static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
595
{
596 597 598
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp32(arg0, t0, s, crf);
    tcg_temp_free(t0);
599 600 601
}
#endif

B
Blue Swirl 已提交
602
static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
603 604 605 606 607 608 609 610 611 612
{
#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 已提交
613
static void gen_cmp(DisasContext *ctx)
614 615 616 617 618 619 620 621 622 623 624 625
{
#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 已提交
626
static void gen_cmpi(DisasContext *ctx)
627 628 629 630 631 632 633 634 635 636 637 638
{
#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 已提交
639
static void gen_cmpl(DisasContext *ctx)
640 641 642 643 644 645 646 647 648 649 650 651
{
#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 已提交
652
static void gen_cmpli(DisasContext *ctx)
653 654 655 656 657 658 659 660 661 662 663 664
{
#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 已提交
665
static void gen_isel(DisasContext *ctx)
666 667 668 669
{
    int l1, l2;
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;
P
pbrook 已提交
670
    TCGv_i32 t0;
671 672 673 674 675

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

    mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
676
    t0 = tcg_temp_new_i32();
677 678
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
679 680 681 682 683 684 685 686
    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 已提交
687
    tcg_temp_free_i32(t0);
688 689
}

B
bellard 已提交
690 691
/***                           Integer arithmetic                          ***/

B
Blue Swirl 已提交
692 693
static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
                                           TCGv arg1, TCGv arg2, int sub)
694 695 696
{
    int l1;
    TCGv t0;
B
bellard 已提交
697

698 699 700
    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 已提交
701
    t0 = tcg_temp_local_new();
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
    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 已提交
723 724
}

B
Blue Swirl 已提交
725 726
static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1,
                                           TCGv arg2, int sub)
727 728
{
    int l1 = gen_new_label();
729 730

#if defined(TARGET_PPC64)
731 732
    if (!(ctx->sf_mode)) {
        TCGv t0, t1;
P
pbrook 已提交
733 734
        t0 = tcg_temp_new();
        t1 = tcg_temp_new();
735

736 737 738 739
        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 已提交
740
        } else {
741 742
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
        }
743 744 745 746
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
        gen_set_label(l1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
747 748
    } else
#endif
749 750 751 752 753 754 755 756
    {
        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);
757
    }
758 759
}

760
/* Common add function */
B
Blue Swirl 已提交
761 762 763
static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                    TCGv arg2, int add_ca, int compute_ca,
                                    int compute_ov)
764 765
{
    TCGv t0, t1;
766

767
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
768
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
769 770
        t0 = ret;
    } else {
P
pbrook 已提交
771
        t0 = tcg_temp_local_new();
772
    }
B
bellard 已提交
773

774
    if (add_ca) {
P
pbrook 已提交
775
        t1 = tcg_temp_local_new();
776 777
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
778 779
    } else {
        TCGV_UNUSED(t1);
780
    }
B
bellard 已提交
781

782 783 784 785 786 787 788 789 790 791
    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 已提交
792

793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
    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 已提交
810
    if (!TCGV_EQUAL(t0, ret)) {
811 812 813
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
814
}
815 816
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
B
Blue Swirl 已提交
817
static void glue(gen_, name)(DisasContext *ctx)                                       \
818 819 820 821 822 823 824 825
{                                                                             \
    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 已提交
826
static void glue(gen_, name)(DisasContext *ctx)                                       \
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
{                                                                             \
    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 已提交
851
static void gen_addi(DisasContext *ctx)
852
{
853 854 855 856 857 858 859 860
    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);
    }
861
}
862
/* addic  addic.*/
B
Blue Swirl 已提交
863 864
static inline void gen_op_addic(DisasContext *ctx, TCGv ret, TCGv arg1,
                                int compute_Rc0)
865
{
866 867 868 869 870 871
    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 已提交
872
        TCGv t0 = tcg_temp_local_new();
873 874 875 876 877 878 879 880 881 882
        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);
    }
883
}
B
Blue Swirl 已提交
884 885

static void gen_addic(DisasContext *ctx)
886
{
887
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
888
}
B
Blue Swirl 已提交
889 890

static void gen_addic_(DisasContext *ctx)
891
{
892
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
893
}
B
Blue Swirl 已提交
894

895
/* addis */
B
Blue Swirl 已提交
896
static void gen_addis(DisasContext *ctx)
897
{
898 899 900 901 902 903 904 905
    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);
    }
906
}
907

B
Blue Swirl 已提交
908 909
static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign, int compute_ov)
910
{
911 912
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
913 914
    TCGv_i32 t0 = tcg_temp_local_new_i32();
    TCGv_i32 t1 = tcg_temp_local_new_i32();
915

916 917 918
    tcg_gen_trunc_tl_i32(t0, arg1);
    tcg_gen_trunc_tl_i32(t1, arg2);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
919
    if (sign) {
920 921 922
        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);
923
        gen_set_label(l3);
924
        tcg_gen_div_i32(t0, t0, t1);
925
    } else {
926
        tcg_gen_divu_i32(t0, t0, t1);
927 928 929 930 931 932 933
    }
    if (compute_ov) {
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
    if (sign) {
934
        tcg_gen_sari_i32(t0, t0, 31);
935 936 937 938 939 940 941
    } 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);
942
    tcg_gen_extu_i32_tl(ret, t0);
P
pbrook 已提交
943 944
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
945 946
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
947
}
948 949
/* Div functions */
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
B
Blue Swirl 已提交
950
static void glue(gen_, name)(DisasContext *ctx)                                       \
951 952 953 954 955 956 957 958 959 960 961
{                                                                             \
    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);
962
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
963 964
static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign, int compute_ov)
965
{
966 967
    int l1 = gen_new_label();
    int l2 = gen_new_label();
968 969 970

    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
    if (sign) {
971
        int l3 = gen_new_label();
972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
        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);
995
}
996
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
B
Blue Swirl 已提交
997
static void glue(gen_, name)(DisasContext *ctx)                                       \
998
{                                                                             \
999 1000 1001
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      sign, compute_ov);                                      \
1002 1003 1004 1005 1006 1007 1008
}
/* 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);
1009
#endif
1010 1011

/* mulhw  mulhw. */
B
Blue Swirl 已提交
1012
static void gen_mulhw(DisasContext *ctx)
1013
{
P
pbrook 已提交
1014
    TCGv_i64 t0, t1;
1015

P
pbrook 已提交
1016 1017
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
#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 已提交
1030 1031
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1032 1033
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1034
}
B
Blue Swirl 已提交
1035

1036
/* mulhwu  mulhwu.  */
B
Blue Swirl 已提交
1037
static void gen_mulhwu(DisasContext *ctx)
1038
{
P
pbrook 已提交
1039
    TCGv_i64 t0, t1;
1040

P
pbrook 已提交
1041 1042
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1043
#if defined(TARGET_PPC64)
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
    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 已提交
1055 1056
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1057 1058
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1059
}
B
Blue Swirl 已提交
1060

1061
/* mullw  mullw. */
B
Blue Swirl 已提交
1062
static void gen_mullw(DisasContext *ctx)
1063
{
1064 1065
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
1066
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1067 1068
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1069
}
B
Blue Swirl 已提交
1070

1071
/* mullwo  mullwo. */
B
Blue Swirl 已提交
1072
static void gen_mullwo(DisasContext *ctx)
1073
{
1074
    int l1;
P
pbrook 已提交
1075
    TCGv_i64 t0, t1;
1076

P
pbrook 已提交
1077 1078
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1079 1080 1081 1082 1083 1084 1085 1086 1087
    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)]);
1088
#endif
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
    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 已提交
1100 1101
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1102 1103
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1104
}
B
Blue Swirl 已提交
1105

1106
/* mulli */
B
Blue Swirl 已提交
1107
static void gen_mulli(DisasContext *ctx)
1108
{
1109 1110
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                    SIMM(ctx->opcode));
1111 1112
}
#if defined(TARGET_PPC64)
1113
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
B
Blue Swirl 已提交
1114
static void glue(gen_, name)(DisasContext *ctx)                                       \
1115
{                                                                             \
P
pbrook 已提交
1116
    gen_helper_##name (cpu_gpr[rD(ctx->opcode)],                              \
1117 1118 1119
                       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)]);                           \
1120
}
1121 1122 1123 1124
/* mulhd  mulhd. */
GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
/* mulhdu  mulhdu. */
GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
B
Blue Swirl 已提交
1125

1126
/* mulld  mulld. */
B
Blue Swirl 已提交
1127
static void gen_mulld(DisasContext *ctx)
1128
{
1129 1130 1131 1132
    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)]);
1133
}
1134 1135
/* mulldo  mulldo. */
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1136
#endif
1137 1138

/* neg neg. nego nego. */
B
Blue Swirl 已提交
1139 1140
static inline void gen_op_arith_neg(DisasContext *ctx, TCGv ret, TCGv arg1,
                                    int ov_check)
1141
{
A
aurel32 已提交
1142 1143
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
1144
    TCGv t0 = tcg_temp_local_new();
1145
#if defined(TARGET_PPC64)
1146
    if (ctx->sf_mode) {
A
aurel32 已提交
1147
        tcg_gen_mov_tl(t0, arg1);
A
aurel32 已提交
1148 1149 1150 1151 1152
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
    } else
#endif
    {
        tcg_gen_ext32s_tl(t0, arg1);
1153 1154 1155 1156 1157 1158 1159 1160
        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 已提交
1161
    tcg_gen_mov_tl(ret, t0);
1162 1163 1164 1165
    if (ov_check) {
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    }
    gen_set_label(l2);
A
aurel32 已提交
1166
    tcg_temp_free(t0);
1167 1168 1169
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
}
B
Blue Swirl 已提交
1170 1171

static void gen_neg(DisasContext *ctx)
1172
{
A
aurel32 已提交
1173
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1174
}
B
Blue Swirl 已提交
1175 1176

static void gen_nego(DisasContext *ctx)
B
bellard 已提交
1177
{
A
aurel32 已提交
1178
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
B
bellard 已提交
1179
}
1180 1181

/* Common subf function */
B
Blue Swirl 已提交
1182 1183 1184
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 已提交
1185
{
1186
    TCGv t0, t1;
1187

1188
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
1189
        (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1190
        t0 = ret;
J
j_mayer 已提交
1191
    } else {
P
pbrook 已提交
1192
        t0 = tcg_temp_local_new();
1193
    }
1194

1195
    if (add_ca) {
P
pbrook 已提交
1196
        t1 = tcg_temp_local_new();
1197 1198
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
1199 1200
    } else {
        TCGV_UNUSED(t1);
1201
    }
B
bellard 已提交
1202

1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
    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 已提交
1221
    } else {
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233
        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 已提交
1234
    if (!TCGV_EQUAL(t0, ret)) {
1235 1236
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
B
bellard 已提交
1237 1238
    }
}
1239 1240
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
B
Blue Swirl 已提交
1241
static void glue(gen_, name)(DisasContext *ctx)                                       \
1242 1243 1244 1245 1246 1247 1248 1249
{                                                                             \
    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 已提交
1250
static void glue(gen_, name)(DisasContext *ctx)                                       \
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
{                                                                             \
    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 已提交
1273

1274
/* subfic */
B
Blue Swirl 已提交
1275
static void gen_subfic(DisasContext *ctx)
B
bellard 已提交
1276
{
1277 1278
    /* Start with XER CA and OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
P
pbrook 已提交
1279
    TCGv t0 = tcg_temp_local_new();
1280 1281 1282 1283 1284 1285
    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 已提交
1286 1287 1288
}

/***                            Integer logical                            ***/
1289
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1290
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1291
{                                                                             \
1292 1293
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
       cpu_gpr[rB(ctx->opcode)]);                                             \
1294
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1295
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1296 1297
}

1298
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1299
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1300
{                                                                             \
1301
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1302
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1303
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1304 1305 1306
}

/* and & and. */
1307
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
B
bellard 已提交
1308
/* andc & andc. */
1309
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
B
Blue Swirl 已提交
1310

1311
/* andi. */
B
Blue Swirl 已提交
1312
static void gen_andi_(DisasContext *ctx)
B
bellard 已提交
1313
{
1314 1315
    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 已提交
1316
}
B
Blue Swirl 已提交
1317

1318
/* andis. */
B
Blue Swirl 已提交
1319
static void gen_andis_(DisasContext *ctx)
B
bellard 已提交
1320
{
1321 1322
    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 已提交
1323
}
B
Blue Swirl 已提交
1324

1325
/* cntlzw */
B
Blue Swirl 已提交
1326
static void gen_cntlzw(DisasContext *ctx)
1327
{
P
pbrook 已提交
1328
    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1329
    if (unlikely(Rc(ctx->opcode) != 0))
P
pbrook 已提交
1330
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1331
}
B
bellard 已提交
1332
/* eqv & eqv. */
1333
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
B
bellard 已提交
1334
/* extsb & extsb. */
1335
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
B
bellard 已提交
1336
/* extsh & extsh. */
1337
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
B
bellard 已提交
1338
/* nand & nand. */
1339
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
B
bellard 已提交
1340
/* nor & nor. */
1341
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
B
Blue Swirl 已提交
1342

1343
/* or & or. */
B
Blue Swirl 已提交
1344
static void gen_or(DisasContext *ctx)
1345
{
1346 1347 1348 1349 1350 1351 1352
    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) {
1353 1354 1355 1356
        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]);
1357
        if (unlikely(Rc(ctx->opcode) != 0))
1358
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1359
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1360
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1361 1362
#if defined(TARGET_PPC64)
    } else {
1363 1364
        int prio = 0;

1365 1366 1367
        switch (rs) {
        case 1:
            /* Set process priority to low */
1368
            prio = 2;
1369 1370 1371
            break;
        case 6:
            /* Set process priority to medium-low */
1372
            prio = 3;
1373 1374 1375
            break;
        case 2:
            /* Set process priority to normal */
1376
            prio = 4;
1377
            break;
1378 1379
#if !defined(CONFIG_USER_ONLY)
        case 31:
A
aurel32 已提交
1380
            if (ctx->mem_idx > 0) {
1381
                /* Set process priority to very low */
1382
                prio = 1;
1383 1384 1385
            }
            break;
        case 5:
A
aurel32 已提交
1386
            if (ctx->mem_idx > 0) {
1387
                /* Set process priority to medium-hight */
1388
                prio = 5;
1389 1390 1391
            }
            break;
        case 3:
A
aurel32 已提交
1392
            if (ctx->mem_idx > 0) {
1393
                /* Set process priority to high */
1394
                prio = 6;
1395 1396 1397
            }
            break;
        case 7:
A
aurel32 已提交
1398
            if (ctx->mem_idx > 1) {
1399
                /* Set process priority to very high */
1400
                prio = 7;
1401 1402 1403
            }
            break;
#endif
1404 1405 1406 1407
        default:
            /* nop */
            break;
        }
1408
        if (prio) {
P
pbrook 已提交
1409
            TCGv t0 = tcg_temp_new();
1410
            gen_load_spr(t0, SPR_PPR);
1411 1412
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1413
            gen_store_spr(SPR_PPR, t0);
1414
            tcg_temp_free(t0);
1415
        }
1416
#endif
1417 1418
    }
}
B
bellard 已提交
1419
/* orc & orc. */
1420
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
B
Blue Swirl 已提交
1421

1422
/* xor & xor. */
B
Blue Swirl 已提交
1423
static void gen_xor(DisasContext *ctx)
1424 1425
{
    /* Optimisation for "set to zero" case */
1426
    if (rS(ctx->opcode) != rB(ctx->opcode))
A
aurel32 已提交
1427
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1428 1429
    else
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1430
    if (unlikely(Rc(ctx->opcode) != 0))
1431
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1432
}
B
Blue Swirl 已提交
1433

1434
/* ori */
B
Blue Swirl 已提交
1435
static void gen_ori(DisasContext *ctx)
B
bellard 已提交
1436
{
1437
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1438

1439 1440
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
1441
        /* XXX: should handle special NOPs for POWER series */
1442
        return;
1443
    }
1444
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1445
}
B
Blue Swirl 已提交
1446

1447
/* oris */
B
Blue Swirl 已提交
1448
static void gen_oris(DisasContext *ctx)
B
bellard 已提交
1449
{
1450
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1451

1452 1453 1454
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1455
    }
1456
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1457
}
B
Blue Swirl 已提交
1458

1459
/* xori */
B
Blue Swirl 已提交
1460
static void gen_xori(DisasContext *ctx)
B
bellard 已提交
1461
{
1462
    target_ulong uimm = UIMM(ctx->opcode);
1463 1464 1465 1466 1467

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

1471
/* xoris */
B
Blue Swirl 已提交
1472
static void gen_xoris(DisasContext *ctx)
B
bellard 已提交
1473
{
1474
    target_ulong uimm = UIMM(ctx->opcode);
1475 1476 1477 1478 1479

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

1483
/* popcntb : PowerPC 2.03 specification */
B
Blue Swirl 已提交
1484
static void gen_popcntb(DisasContext *ctx)
1485 1486 1487
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
P
pbrook 已提交
1488
        gen_helper_popcntb_64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1489 1490
    else
#endif
P
pbrook 已提交
1491
        gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1492 1493 1494 1495
}

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

1498
/* cntlzd */
B
Blue Swirl 已提交
1499
static void gen_cntlzd(DisasContext *ctx)
1500
{
P
pbrook 已提交
1501
    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1502 1503 1504
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1505 1506
#endif

B
bellard 已提交
1507
/***                             Integer rotate                            ***/
B
Blue Swirl 已提交
1508

1509
/* rlwimi & rlwimi. */
B
Blue Swirl 已提交
1510
static void gen_rlwimi(DisasContext *ctx)
B
bellard 已提交
1511
{
1512
    uint32_t mb, me, sh;
B
bellard 已提交
1513 1514 1515

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1516
    sh = SH(ctx->opcode);
1517 1518 1519 1520
    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 已提交
1521 1522
        TCGv t1;
        TCGv t0 = tcg_temp_new();
1523
#if defined(TARGET_PPC64)
P
pbrook 已提交
1524 1525 1526 1527 1528
        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);
1529 1530 1531
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1532
#if defined(TARGET_PPC64)
1533 1534
        mb += 32;
        me += 32;
1535
#endif
1536
        mask = MASK(mb, me);
P
pbrook 已提交
1537
        t1 = tcg_temp_new();
1538 1539 1540 1541 1542 1543
        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);
    }
1544
    if (unlikely(Rc(ctx->opcode) != 0))
1545
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1546
}
B
Blue Swirl 已提交
1547

1548
/* rlwinm & rlwinm. */
B
Blue Swirl 已提交
1549
static void gen_rlwinm(DisasContext *ctx)
B
bellard 已提交
1550 1551
{
    uint32_t mb, me, sh;
1552

B
bellard 已提交
1553 1554 1555
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1556 1557 1558 1559 1560

    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 已提交
1561
            TCGv t0 = tcg_temp_new();
1562 1563 1564 1565
            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 已提交
1566
        }
1567
    } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
P
pbrook 已提交
1568
        TCGv t0 = tcg_temp_new();
1569 1570 1571 1572 1573
        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 已提交
1574
        TCGv t0 = tcg_temp_new();
1575
#if defined(TARGET_PPC64)
P
pbrook 已提交
1576
        TCGv_i32 t1 = tcg_temp_new_i32();
1577 1578 1579
        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 已提交
1580
        tcg_temp_free_i32(t1);
1581 1582 1583
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1584
#if defined(TARGET_PPC64)
1585 1586
        mb += 32;
        me += 32;
1587
#endif
1588 1589 1590
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
        tcg_temp_free(t0);
    }
1591
    if (unlikely(Rc(ctx->opcode) != 0))
1592
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1593
}
B
Blue Swirl 已提交
1594

1595
/* rlwnm & rlwnm. */
B
Blue Swirl 已提交
1596
static void gen_rlwnm(DisasContext *ctx)
B
bellard 已提交
1597 1598
{
    uint32_t mb, me;
1599 1600
    TCGv t0;
#if defined(TARGET_PPC64)
P
pbrook 已提交
1601
    TCGv_i32 t1, t2;
1602
#endif
B
bellard 已提交
1603 1604 1605

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1606
    t0 = tcg_temp_new();
1607
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1608
#if defined(TARGET_PPC64)
P
pbrook 已提交
1609 1610
    t1 = tcg_temp_new_i32();
    t2 = tcg_temp_new_i32();
1611 1612 1613 1614
    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 已提交
1615 1616
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
1617 1618 1619
#else
    tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
#endif
1620 1621 1622 1623 1624
    if (unlikely(mb != 0 || me != 31)) {
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
1625
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1626
    } else {
1627
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
B
bellard 已提交
1628
    }
1629
    tcg_temp_free(t0);
1630
    if (unlikely(Rc(ctx->opcode) != 0))
1631
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1632 1633
}

1634 1635
#if defined(TARGET_PPC64)
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1636
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1637 1638 1639
{                                                                             \
    gen_##name(ctx, 0);                                                       \
}                                                                             \
B
Blue Swirl 已提交
1640 1641
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1642 1643 1644 1645
{                                                                             \
    gen_##name(ctx, 1);                                                       \
}
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1646
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1647 1648 1649
{                                                                             \
    gen_##name(ctx, 0, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1650 1651
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1652 1653 1654
{                                                                             \
    gen_##name(ctx, 0, 1);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1655 1656
                                                                              \
static void glue(gen_, name##2)(DisasContext *ctx)                            \
1657 1658 1659
{                                                                             \
    gen_##name(ctx, 1, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1660 1661
                                                                              \
static void glue(gen_, name##3)(DisasContext *ctx)                            \
1662 1663 1664
{                                                                             \
    gen_##name(ctx, 1, 1);                                                    \
}
J
j_mayer 已提交
1665

B
Blue Swirl 已提交
1666 1667
static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
                              uint32_t sh)
J
j_mayer 已提交
1668
{
1669 1670 1671 1672 1673
    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 已提交
1674
        TCGv t0 = tcg_temp_new();
1675
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1676
        if (likely(mb == 0 && me == 63)) {
1677
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1678 1679
        } else {
            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
J
j_mayer 已提交
1680
        }
1681
        tcg_temp_free(t0);
J
j_mayer 已提交
1682 1683
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1684
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
J
j_mayer 已提交
1685
}
1686
/* rldicl - rldicl. */
B
Blue Swirl 已提交
1687
static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1688
{
J
j_mayer 已提交
1689
    uint32_t sh, mb;
1690

J
j_mayer 已提交
1691 1692
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1693
    gen_rldinm(ctx, mb, 63, sh);
1694
}
J
j_mayer 已提交
1695
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1696
/* rldicr - rldicr. */
B
Blue Swirl 已提交
1697
static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1698
{
J
j_mayer 已提交
1699
    uint32_t sh, me;
1700

J
j_mayer 已提交
1701 1702
    sh = SH(ctx->opcode) | (shn << 5);
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1703
    gen_rldinm(ctx, 0, me, sh);
1704
}
J
j_mayer 已提交
1705
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1706
/* rldic - rldic. */
B
Blue Swirl 已提交
1707
static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1708
{
J
j_mayer 已提交
1709
    uint32_t sh, mb;
1710

J
j_mayer 已提交
1711 1712
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1713 1714 1715 1716
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

B
Blue Swirl 已提交
1717
static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
J
j_mayer 已提交
1718
{
1719
    TCGv t0;
1720 1721 1722

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1723
    t0 = tcg_temp_new();
1724
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1725
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
J
j_mayer 已提交
1726
    if (unlikely(mb != 0 || me != 63)) {
1727 1728 1729 1730 1731
        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 已提交
1732
    if (unlikely(Rc(ctx->opcode) != 0))
1733
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1734
}
J
j_mayer 已提交
1735

1736
/* rldcl - rldcl. */
B
Blue Swirl 已提交
1737
static inline void gen_rldcl(DisasContext *ctx, int mbn)
1738
{
J
j_mayer 已提交
1739
    uint32_t mb;
1740

J
j_mayer 已提交
1741
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1742
    gen_rldnm(ctx, mb, 63);
1743
}
1744
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1745
/* rldcr - rldcr. */
B
Blue Swirl 已提交
1746
static inline void gen_rldcr(DisasContext *ctx, int men)
1747
{
J
j_mayer 已提交
1748
    uint32_t me;
1749

J
j_mayer 已提交
1750
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1751
    gen_rldnm(ctx, 0, me);
1752
}
1753
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1754
/* rldimi - rldimi. */
B
Blue Swirl 已提交
1755
static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1756
{
1757
    uint32_t sh, mb, me;
1758

J
j_mayer 已提交
1759 1760
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
1761
    me = 63 - sh;
1762 1763 1764 1765 1766 1767
    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 已提交
1768
        t0 = tcg_temp_new();
1769
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
P
pbrook 已提交
1770
        t1 = tcg_temp_new();
1771 1772 1773 1774 1775 1776
        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 已提交
1777 1778
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1779
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1780
}
1781
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1782 1783
#endif

B
bellard 已提交
1784
/***                             Integer shift                             ***/
B
Blue Swirl 已提交
1785

1786
/* slw & slw. */
B
Blue Swirl 已提交
1787
static void gen_slw(DisasContext *ctx)
1788
{
1789
    TCGv t0, t1;
1790

1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804
    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);
1805
    tcg_temp_free(t0);
1806
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1807 1808 1809
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1810

1811
/* sraw & sraw. */
B
Blue Swirl 已提交
1812
static void gen_sraw(DisasContext *ctx)
1813
{
P
pbrook 已提交
1814 1815
    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1816 1817 1818
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1819

1820
/* srawi & srawi. */
B
Blue Swirl 已提交
1821
static void gen_srawi(DisasContext *ctx)
B
bellard 已提交
1822
{
1823 1824 1825
    int sh = SH(ctx->opcode);
    if (sh != 0) {
        int l1, l2;
1826
        TCGv t0;
1827 1828
        l1 = gen_new_label();
        l2 = gen_new_label();
P
pbrook 已提交
1829
        t0 = tcg_temp_local_new();
1830 1831 1832 1833
        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);
1834
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1835 1836
        tcg_gen_br(l2);
        gen_set_label(l1);
1837
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1838
        gen_set_label(l2);
1839 1840 1841
        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);
1842 1843
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1844
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1845
    }
1846
    if (unlikely(Rc(ctx->opcode) != 0))
1847
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1848
}
B
Blue Swirl 已提交
1849

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

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

1875 1876
#if defined(TARGET_PPC64)
/* sld & sld. */
B
Blue Swirl 已提交
1877
static void gen_sld(DisasContext *ctx)
1878
{
1879
    TCGv t0, t1;
1880

1881 1882 1883 1884 1885 1886 1887 1888 1889
    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);
1890
    tcg_temp_free(t0);
1891 1892 1893
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1894

1895
/* srad & srad. */
B
Blue Swirl 已提交
1896
static void gen_srad(DisasContext *ctx)
1897
{
P
pbrook 已提交
1898 1899
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1900 1901 1902
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1903
/* sradi & sradi. */
B
Blue Swirl 已提交
1904
static inline void gen_sradi(DisasContext *ctx, int n)
1905
{
1906
    int sh = SH(ctx->opcode) + (n << 5);
1907
    if (sh != 0) {
1908
        int l1, l2;
1909
        TCGv t0;
1910 1911
        l1 = gen_new_label();
        l2 = gen_new_label();
P
pbrook 已提交
1912
        t0 = tcg_temp_local_new();
1913
        tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
1914 1915
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1916
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1917 1918
        tcg_gen_br(l2);
        gen_set_label(l1);
1919
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1920
        gen_set_label(l2);
1921
        tcg_temp_free(t0);
1922 1923 1924
        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)]);
1925
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1926 1927
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1928
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1929
}
B
Blue Swirl 已提交
1930 1931

static void gen_sradi0(DisasContext *ctx)
1932 1933 1934
{
    gen_sradi(ctx, 0);
}
B
Blue Swirl 已提交
1935 1936

static void gen_sradi1(DisasContext *ctx)
1937 1938 1939
{
    gen_sradi(ctx, 1);
}
B
Blue Swirl 已提交
1940

1941
/* srd & srd. */
B
Blue Swirl 已提交
1942
static void gen_srd(DisasContext *ctx)
1943
{
1944
    TCGv t0, t1;
1945

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

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

1981 1982 1983
#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);
1984

1985
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
B
Blue Swirl 已提交
1986
static void gen_f##name(DisasContext *ctx)                                    \
1987
{                                                                             \
1988
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
1989
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
1990 1991
        return;                                                               \
    }                                                                         \
1992 1993
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
1994
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
1995 1996
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
                     cpu_fpr[rB(ctx->opcode)]);                               \
1997
    if (isfloat) {                                                            \
A
aurel32 已提交
1998
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
1999
    }                                                                         \
A
aurel32 已提交
2000 2001
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2002
}
2003 2004 2005
#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);
2006

2007
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
B
Blue Swirl 已提交
2008
static void gen_f##name(DisasContext *ctx)                                    \
2009
{                                                                             \
2010
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2011
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2012 2013
        return;                                                               \
    }                                                                         \
2014 2015
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2016
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2017 2018
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
                       cpu_fpr[rC(ctx->opcode)]);                             \
2019
    if (isfloat) {                                                            \
A
aurel32 已提交
2020
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2021
    }                                                                         \
A
aurel32 已提交
2022 2023
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2024
}
2025 2026 2027
#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);
2028

2029
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
B
Blue Swirl 已提交
2030
static void gen_f##name(DisasContext *ctx)                                    \
2031
{                                                                             \
2032
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2033
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2034 2035
        return;                                                               \
    }                                                                         \
2036 2037
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2038
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2039 2040 2041
    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 已提交
2042 2043
}

2044
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
B
Blue Swirl 已提交
2045
static void gen_f##name(DisasContext *ctx)                                    \
2046
{                                                                             \
2047
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2048
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2049 2050
        return;                                                               \
    }                                                                         \
2051 2052
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2053
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2054 2055 2056
    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 已提交
2057 2058
}

2059
/* fadd - fadds */
2060
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2061
/* fdiv - fdivs */
2062
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2063
/* fmul - fmuls */
2064
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2065

2066
/* fre */
2067
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2068

2069
/* fres */
2070
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2071

2072
/* frsqrte */
2073 2074 2075
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
B
Blue Swirl 已提交
2076
static void gen_frsqrtes(DisasContext *ctx)
2077
{
A
aurel32 已提交
2078
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2079
        gen_exception(ctx, POWERPC_EXCP_FPU);
A
aurel32 已提交
2080 2081
        return;
    }
2082 2083
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2084 2085 2086 2087
    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);
2088
}
B
bellard 已提交
2089

2090
/* fsel */
2091
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2092
/* fsub - fsubs */
2093
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2094
/* Optional: */
B
Blue Swirl 已提交
2095

2096
/* fsqrt */
B
Blue Swirl 已提交
2097
static void gen_fsqrt(DisasContext *ctx)
2098
{
2099
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2100
        gen_exception(ctx, POWERPC_EXCP_FPU);
2101 2102
        return;
    }
2103 2104
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2105
    gen_reset_fpstatus();
A
aurel32 已提交
2106 2107
    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);
2108
}
B
bellard 已提交
2109

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

/***                     Floating-Point multiply-and-add                   ***/
2125
/* fmadd - fmadds */
2126
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2127
/* fmsub - fmsubs */
2128
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2129
/* fnmadd - fnmadds */
2130
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2131
/* fnmsub - fnmsubs */
2132
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2133 2134 2135

/***                     Floating-Point round & convert                    ***/
/* fctiw */
2136
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2137
/* fctiwz */
2138
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2139
/* frsp */
2140
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
2141 2142
#if defined(TARGET_PPC64)
/* fcfid */
2143
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
2144
/* fctid */
2145
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2146
/* fctidz */
2147
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2148
#endif
B
bellard 已提交
2149

2150
/* frin */
2151
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2152
/* friz */
2153
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2154
/* frip */
2155
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2156
/* frim */
2157
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2158

B
bellard 已提交
2159
/***                         Floating-Point compare                        ***/
B
Blue Swirl 已提交
2160

2161
/* fcmpo */
B
Blue Swirl 已提交
2162
static void gen_fcmpo(DisasContext *ctx)
B
bellard 已提交
2163
{
A
aurel32 已提交
2164
    TCGv_i32 crf;
2165
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2166
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2167 2168
        return;
    }
2169 2170
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2171
    gen_reset_fpstatus();
A
aurel32 已提交
2172 2173
    crf = tcg_const_i32(crfD(ctx->opcode));
    gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2174
    tcg_temp_free_i32(crf);
A
aurel32 已提交
2175
    gen_helper_float_check_status();
B
bellard 已提交
2176 2177 2178
}

/* fcmpu */
B
Blue Swirl 已提交
2179
static void gen_fcmpu(DisasContext *ctx)
B
bellard 已提交
2180
{
A
aurel32 已提交
2181
    TCGv_i32 crf;
2182
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2183
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2184 2185
        return;
    }
2186 2187
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2188
    gen_reset_fpstatus();
A
aurel32 已提交
2189 2190
    crf = tcg_const_i32(crfD(ctx->opcode));
    gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2191
    tcg_temp_free_i32(crf);
A
aurel32 已提交
2192
    gen_helper_float_check_status();
B
bellard 已提交
2193 2194
}

2195 2196
/***                         Floating-point move                           ***/
/* fabs */
2197 2198
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2199 2200

/* fmr  - fmr. */
2201
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
B
Blue Swirl 已提交
2202
static void gen_fmr(DisasContext *ctx)
2203
{
2204
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2205
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2206 2207
        return;
    }
A
aurel32 已提交
2208 2209
    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);
2210 2211 2212
}

/* fnabs */
2213 2214
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2215
/* fneg */
2216 2217
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2218

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

2221
/* mcrfs */
B
Blue Swirl 已提交
2222
static void gen_mcrfs(DisasContext *ctx)
B
bellard 已提交
2223
{
2224 2225
    int bfa;

2226
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2227
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2228 2229
        return;
    }
2230
    bfa = 4 * (7 - crfS(ctx->opcode));
2231 2232
    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 已提交
2233
    tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
B
bellard 已提交
2234 2235 2236
}

/* mffs */
B
Blue Swirl 已提交
2237
static void gen_mffs(DisasContext *ctx)
B
bellard 已提交
2238
{
2239
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2240
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2241 2242
        return;
    }
2243
    gen_reset_fpstatus();
A
aurel32 已提交
2244 2245
    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 已提交
2246 2247 2248
}

/* mtfsb0 */
B
Blue Swirl 已提交
2249
static void gen_mtfsb0(DisasContext *ctx)
B
bellard 已提交
2250
{
B
bellard 已提交
2251
    uint8_t crb;
2252

2253
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2254
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2255 2256
        return;
    }
A
aurel32 已提交
2257
    crb = 31 - crbD(ctx->opcode);
2258
    gen_reset_fpstatus();
A
aurel32 已提交
2259
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2260 2261 2262 2263
        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 已提交
2264 2265 2266
        gen_helper_fpscr_clrbit(t0);
        tcg_temp_free_i32(t0);
    }
2267
    if (unlikely(Rc(ctx->opcode) != 0)) {
2268
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2269
    }
B
bellard 已提交
2270 2271 2272
}

/* mtfsb1 */
B
Blue Swirl 已提交
2273
static void gen_mtfsb1(DisasContext *ctx)
B
bellard 已提交
2274
{
B
bellard 已提交
2275
    uint8_t crb;
2276

2277
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2278
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2279 2280
        return;
    }
A
aurel32 已提交
2281
    crb = 31 - crbD(ctx->opcode);
2282 2283
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
A
aurel32 已提交
2284
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2285 2286 2287 2288
        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 已提交
2289
        gen_helper_fpscr_setbit(t0);
2290
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2291
    }
2292
    if (unlikely(Rc(ctx->opcode) != 0)) {
2293
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2294 2295
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2296
    gen_helper_float_check_status();
B
bellard 已提交
2297 2298 2299
}

/* mtfsf */
B
Blue Swirl 已提交
2300
static void gen_mtfsf(DisasContext *ctx)
B
bellard 已提交
2301
{
2302
    TCGv_i32 t0;
B
blueswir1 已提交
2303
    int L = ctx->opcode & 0x02000000;
A
aurel32 已提交
2304

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

/* mtfsfi */
B
Blue Swirl 已提交
2326
static void gen_mtfsfi(DisasContext *ctx)
B
bellard 已提交
2327
{
2328
    int bf, sh;
2329 2330
    TCGv_i64 t0;
    TCGv_i32 t1;
2331

2332
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2333
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2334 2335
        return;
    }
2336 2337
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
2338 2339
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2340
    gen_reset_fpstatus();
2341
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
A
aurel32 已提交
2342 2343
    t1 = tcg_const_i32(1 << sh);
    gen_helper_store_fpscr(t0, t1);
2344 2345
    tcg_temp_free_i64(t0);
    tcg_temp_free_i32(t1);
2346
    if (unlikely(Rc(ctx->opcode) != 0)) {
2347
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2348 2349
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2350
    gen_helper_float_check_status();
B
bellard 已提交
2351 2352
}

2353 2354
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
B
Blue Swirl 已提交
2355 2356
static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
                                      target_long maskl)
2357 2358 2359
{
    target_long simm = SIMM(ctx->opcode);

2360
    simm &= ~maskl;
A
aurel32 已提交
2361 2362 2363 2364 2365 2366
    if (rA(ctx->opcode) == 0) {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_movi_tl(EA, (uint32_t)simm);
        } else
#endif
2367
        tcg_gen_movi_tl(EA, simm);
A
aurel32 已提交
2368
    } else if (likely(simm != 0)) {
2369
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
A
aurel32 已提交
2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380
#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
2381
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2382
    }
2383 2384
}

B
Blue Swirl 已提交
2385
static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2386
{
A
aurel32 已提交
2387 2388 2389 2390 2391 2392
    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
2393
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2394
    } else {
2395
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2396 2397 2398 2399 2400 2401
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
2402 2403
}

B
Blue Swirl 已提交
2404
static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2405
{
A
aurel32 已提交
2406
    if (rA(ctx->opcode) == 0) {
2407
        tcg_gen_movi_tl(EA, 0);
A
aurel32 已提交
2408 2409 2410 2411 2412 2413 2414 2415 2416 2417
    } 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 已提交
2418 2419
static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                target_long val)
A
aurel32 已提交
2420 2421 2422 2423 2424 2425 2426
{
    tcg_gen_addi_tl(ret, arg1, val);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode) {
        tcg_gen_ext32u_tl(ret, ret);
    }
#endif
2427 2428
}

B
Blue Swirl 已提交
2429
static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446
{
    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);
}

2447
/***                             Integer load                              ***/
B
Blue Swirl 已提交
2448
static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2449 2450 2451 2452
{
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2453
static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2454 2455 2456 2457
{
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
}

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

B
Blue Swirl 已提交
2466
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2467
{
A
aurel32 已提交
2468 2469
    if (unlikely(ctx->le_mode)) {
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2470
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2471 2472 2473 2474
        tcg_gen_ext16s_tl(arg1, arg1);
    } else {
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2475 2476
}

B
Blue Swirl 已提交
2477
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2478
{
A
aurel32 已提交
2479 2480
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2481
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2482
    }
A
aurel32 已提交
2483 2484
}

A
aurel32 已提交
2485
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
2486
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2487
{
B
blueswir1 已提交
2488
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2489
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2490 2491
        tcg_gen_bswap32_tl(arg1, arg1);
        tcg_gen_ext32s_tl(arg1, arg1);
A
aurel32 已提交
2492
    } else
A
aurel32 已提交
2493
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2494
}
A
aurel32 已提交
2495
#endif
A
aurel32 已提交
2496

B
Blue Swirl 已提交
2497
static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2498
{
A
aurel32 已提交
2499 2500
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2501
        tcg_gen_bswap64_i64(arg1, arg1);
A
aurel32 已提交
2502
    }
A
aurel32 已提交
2503 2504
}

B
Blue Swirl 已提交
2505
static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2506
{
A
aurel32 已提交
2507
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2508 2509
}

B
Blue Swirl 已提交
2510
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2511
{
A
aurel32 已提交
2512 2513 2514
    if (unlikely(ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2515
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2516 2517 2518 2519 2520
        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 已提交
2521 2522
}

B
Blue Swirl 已提交
2523
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2524
{
A
aurel32 已提交
2525
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2526 2527 2528
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2529 2530 2531 2532 2533
        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 已提交
2534 2535
}

B
Blue Swirl 已提交
2536
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2537
{
A
aurel32 已提交
2538
    if (unlikely(ctx->le_mode)) {
P
pbrook 已提交
2539
        TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
2540
        tcg_gen_bswap64_i64(t0, arg1);
A
aurel32 已提交
2541
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
P
pbrook 已提交
2542
        tcg_temp_free_i64(t0);
A
aurel32 已提交
2543
    } else
A
aurel32 已提交
2544
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2545 2546
}

2547
#define GEN_LD(name, ldop, opc, type)                                         \
B
Blue Swirl 已提交
2548
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2549
{                                                                             \
A
aurel32 已提交
2550 2551 2552 2553 2554
    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 已提交
2555
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2556 2557
}

2558
#define GEN_LDU(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
2559
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2560
{                                                                             \
A
aurel32 已提交
2561
    TCGv EA;                                                                  \
2562 2563
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2564
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2565
        return;                                                               \
2566
    }                                                                         \
A
aurel32 已提交
2567
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2568
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2569
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2570
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2571
    else                                                                      \
A
aurel32 已提交
2572 2573
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2574 2575
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2576 2577
}

2578
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2579
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2580
{                                                                             \
A
aurel32 已提交
2581
    TCGv EA;                                                                  \
2582 2583
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2584
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2585
        return;                                                               \
2586
    }                                                                         \
A
aurel32 已提交
2587
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2588
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2589 2590
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2591 2592
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2593 2594
}

2595
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
B
Blue Swirl 已提交
2596
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2597
{                                                                             \
A
aurel32 已提交
2598 2599 2600 2601 2602
    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 已提交
2603
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2604 2605
}

2606 2607 2608 2609 2610
#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 已提交
2611 2612

/* lbz lbzu lbzux lbzx */
2613
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2614
/* lha lhau lhaux lhax */
2615
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2616
/* lhz lhzu lhzux lhzx */
2617
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2618
/* lwz lwzu lwzux lwzx */
2619
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2620 2621
#if defined(TARGET_PPC64)
/* lwaux */
2622
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2623
/* lwax */
2624
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2625
/* ldux */
2626
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2627
/* ldx */
2628
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
B
Blue Swirl 已提交
2629 2630

static void gen_ld(DisasContext *ctx)
2631
{
A
aurel32 已提交
2632
    TCGv EA;
2633 2634 2635
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
A
aurel32 已提交
2636
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2637 2638 2639
            return;
        }
    }
A
aurel32 已提交
2640
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2641
    EA = tcg_temp_new();
A
aurel32 已提交
2642
    gen_addr_imm_index(ctx, EA, 0x03);
2643 2644
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2645
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2646 2647
    } else {
        /* ld - ldu */
A
aurel32 已提交
2648
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2649 2650
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2651 2652
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2653
}
B
Blue Swirl 已提交
2654

2655
/* lq */
B
Blue Swirl 已提交
2656
static void gen_lq(DisasContext *ctx)
2657 2658
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2659
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2660 2661
#else
    int ra, rd;
A
aurel32 已提交
2662
    TCGv EA;
2663 2664

    /* Restore CPU state */
A
aurel32 已提交
2665
    if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2666
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2667 2668 2669 2670 2671
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
A
aurel32 已提交
2672
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2673 2674
        return;
    }
A
aurel32 已提交
2675
    if (unlikely(ctx->le_mode)) {
2676
        /* Little-endian mode is not handled */
A
aurel32 已提交
2677
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2678 2679
        return;
    }
A
aurel32 已提交
2680
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2681
    EA = tcg_temp_new();
A
aurel32 已提交
2682 2683 2684 2685
    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 已提交
2686
    tcg_temp_free(EA);
2687 2688
#endif
}
2689
#endif
B
bellard 已提交
2690 2691

/***                              Integer store                            ***/
2692
#define GEN_ST(name, stop, opc, type)                                         \
B
Blue Swirl 已提交
2693
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2694
{                                                                             \
A
aurel32 已提交
2695 2696 2697 2698 2699
    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 已提交
2700
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2701 2702
}

2703
#define GEN_STU(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
2704
static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2705
{                                                                             \
A
aurel32 已提交
2706
    TCGv EA;                                                                  \
2707
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2708
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2709
        return;                                                               \
2710
    }                                                                         \
A
aurel32 已提交
2711
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2712
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2713
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2714
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2715
    else                                                                      \
A
aurel32 已提交
2716 2717
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2718 2719
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2720 2721
}

2722
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2723
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2724
{                                                                             \
A
aurel32 已提交
2725
    TCGv EA;                                                                  \
2726
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2727
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2728
        return;                                                               \
2729
    }                                                                         \
A
aurel32 已提交
2730
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2731
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2732 2733
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2734 2735
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2736 2737
}

2738
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
B
Blue Swirl 已提交
2739
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
2740
{                                                                             \
A
aurel32 已提交
2741 2742 2743 2744 2745
    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 已提交
2746
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2747 2748
}

2749 2750 2751 2752 2753
#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 已提交
2754 2755

/* stb stbu stbux stbx */
2756
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
B
bellard 已提交
2757
/* sth sthu sthux sthx */
2758
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2759
/* stw stwu stwux stwx */
2760
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2761
#if defined(TARGET_PPC64)
2762 2763
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
B
Blue Swirl 已提交
2764 2765

static void gen_std(DisasContext *ctx)
2766
{
2767
    int rs;
A
aurel32 已提交
2768
    TCGv EA;
2769 2770 2771 2772

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2773
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2774 2775
#else
        /* stq */
A
aurel32 已提交
2776
        if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2777
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2778 2779 2780
            return;
        }
        if (unlikely(rs & 1)) {
A
aurel32 已提交
2781
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2782 2783
            return;
        }
A
aurel32 已提交
2784
        if (unlikely(ctx->le_mode)) {
2785
            /* Little-endian mode is not handled */
A
aurel32 已提交
2786
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2787 2788
            return;
        }
A
aurel32 已提交
2789
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2790
        EA = tcg_temp_new();
A
aurel32 已提交
2791 2792 2793 2794
        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 已提交
2795
        tcg_temp_free(EA);
2796 2797 2798 2799 2800
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
A
aurel32 已提交
2801
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2802 2803 2804
                return;
            }
        }
A
aurel32 已提交
2805
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2806
        EA = tcg_temp_new();
A
aurel32 已提交
2807 2808
        gen_addr_imm_index(ctx, EA, 0x03);
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2809
        if (Rc(ctx->opcode))
A
aurel32 已提交
2810 2811
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
2812 2813 2814
    }
}
#endif
B
bellard 已提交
2815 2816
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
2817
static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2818
{
A
aurel32 已提交
2819 2820
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2821
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2822
    }
A
aurel32 已提交
2823
}
2824
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
A
aurel32 已提交
2825

B
bellard 已提交
2826
/* lwbrx */
2827
static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2828
{
A
aurel32 已提交
2829 2830
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2831
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2832
    }
A
aurel32 已提交
2833
}
2834
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
A
aurel32 已提交
2835

B
bellard 已提交
2836
/* sthbrx */
2837
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2838
{
A
aurel32 已提交
2839 2840 2841
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2842
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2843 2844 2845 2846 2847
        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 已提交
2848
}
2849
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
A
aurel32 已提交
2850

B
bellard 已提交
2851
/* stwbrx */
2852
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2853
{
A
aurel32 已提交
2854
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2855 2856 2857
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2858 2859 2860 2861 2862
        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 已提交
2863
}
2864
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2865 2866

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

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

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

/***                    Integer load and store strings                     ***/
2901

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

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
2920 2921 2922
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
A
aurel32 已提交
2923
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
2924
        return;
B
bellard 已提交
2925
    }
A
aurel32 已提交
2926
    gen_set_access_type(ctx, ACCESS_INT);
2927
    /* NIP cannot be restored if the memory exception comes from an helper */
2928
    gen_update_nip(ctx, ctx->nip - 4);
2929
    t0 = tcg_temp_new();
A
aurel32 已提交
2930
    gen_addr_register(ctx, t0);
2931 2932 2933 2934 2935 2936
    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 已提交
2937 2938 2939
}

/* lswx */
B
Blue Swirl 已提交
2940
static void gen_lswx(DisasContext *ctx)
B
bellard 已提交
2941
{
A
aurel32 已提交
2942 2943 2944
    TCGv t0;
    TCGv_i32 t1, t2, t3;
    gen_set_access_type(ctx, ACCESS_INT);
2945
    /* NIP cannot be restored if the memory exception comes from an helper */
2946
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2947 2948 2949 2950 2951
    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));
2952 2953 2954 2955 2956
    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 已提交
2957 2958 2959
}

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

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

/***                        Memory synchronisation                         ***/
/* eieio */
B
Blue Swirl 已提交
3002
static void gen_eieio(DisasContext *ctx)
B
bellard 已提交
3003 3004 3005 3006
{
}

/* isync */
B
Blue Swirl 已提交
3007
static void gen_isync(DisasContext *ctx)
B
bellard 已提交
3008
{
A
aurel32 已提交
3009
    gen_stop_exception(ctx);
B
bellard 已提交
3010 3011
}

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

3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044
#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 已提交
3045
/* stwcx. */
B
Blue Swirl 已提交
3046
static void gen_stwcx_(DisasContext *ctx)
B
bellard 已提交
3047
{
A
aurel32 已提交
3048 3049 3050 3051
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3052
    gen_check_align(ctx, t0, 0x03);
3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069
#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
3070
    tcg_temp_free(t0);
B
bellard 已提交
3071 3072
}

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

/* stdcx. */
B
Blue Swirl 已提交
3090
static void gen_stdcx_(DisasContext *ctx)
J
j_mayer 已提交
3091
{
A
aurel32 已提交
3092 3093 3094 3095
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3096
    gen_check_align(ctx, t0, 0x07);
3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112
#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
3113
    tcg_temp_free(t0);
J
j_mayer 已提交
3114 3115 3116
}
#endif /* defined(TARGET_PPC64) */

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

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

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

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

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

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

3203 3204 3205 3206 3207 3208
#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 已提交
3209
static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3210 3211 3212
{
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
A
aurel32 已提交
3213
    gen_qemu_ld32u(ctx, t0, arg2);
3214 3215 3216 3217 3218
    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 已提交
3219

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

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

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

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

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

3296 3297 3298 3299 3300 3301
#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 已提交
3302
static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3303 3304 3305 3306 3307 3308
{
    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 已提交
3309
    gen_qemu_st32(ctx, t1, arg2);
3310 3311
    tcg_temp_free(t1);
}
B
bellard 已提交
3312 3313

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

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

/***                                Branch                                 ***/
B
Blue Swirl 已提交
3330
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3331 3332 3333
{
    TranslationBlock *tb;
    tb = ctx->tb;
3334 3335 3336 3337
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        dest = (uint32_t) dest;
#endif
B
bellard 已提交
3338
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3339
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3340
        tcg_gen_goto_tb(n);
3341
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
B
bellard 已提交
3342
        tcg_gen_exit_tb((long)tb + n);
3343
    } else {
3344
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3345 3346
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3347
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3348 3349 3350
                ctx->exception == POWERPC_EXCP_BRANCH) {
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
A
aurel32 已提交
3351
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3352 3353 3354
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3355
                gen_debug_exception(ctx);
3356 3357
            }
        }
B
bellard 已提交
3358
        tcg_gen_exit_tb(0);
3359
    }
B
bellard 已提交
3360 3361
}

B
Blue Swirl 已提交
3362
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3363 3364
{
#if defined(TARGET_PPC64)
3365 3366
    if (ctx->sf_mode == 0)
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3367 3368
    else
#endif
3369
        tcg_gen_movi_tl(cpu_lr, nip);
3370 3371
}

B
bellard 已提交
3372
/* b ba bl bla */
B
Blue Swirl 已提交
3373
static void gen_b(DisasContext *ctx)
B
bellard 已提交
3374
{
3375
    target_ulong li, target;
B
bellard 已提交
3376

3377
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3378
    /* sign extend LI */
3379
#if defined(TARGET_PPC64)
3380 3381 3382
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
3383
#endif
3384
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3385
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
3386
        target = ctx->nip + li - 4;
B
bellard 已提交
3387
    else
3388
        target = li;
3389 3390
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3391
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3392 3393
}

3394 3395 3396 3397
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

B
Blue Swirl 已提交
3398
static inline void gen_bcond(DisasContext *ctx, int type)
3399 3400
{
    uint32_t bo = BO(ctx->opcode);
3401 3402
    int l1 = gen_new_label();
    TCGv target;
3403

3404
    ctx->exception = POWERPC_EXCP_BRANCH;
3405
    if (type == BCOND_LR || type == BCOND_CTR) {
P
pbrook 已提交
3406
        target = tcg_temp_local_new();
3407 3408 3409 3410
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3411 3412
    } else {
        TCGV_UNUSED(target);
3413
    }
3414 3415
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3416 3417 3418
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3419
        TCGv temp = tcg_temp_new();
3420
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3421
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3422 3423 3424
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3425
#if defined(TARGET_PPC64)
3426 3427 3428
        if (!ctx->sf_mode)
            tcg_gen_ext32u_tl(temp, cpu_ctr);
        else
3429
#endif
3430 3431 3432 3433 3434
            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);
3435
        }
P
pbrook 已提交
3436
        tcg_temp_free(temp);
3437 3438 3439 3440 3441
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
3442
        TCGv_i32 temp = tcg_temp_new_i32();
3443

3444
        if (bo & 0x8) {
3445 3446
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3447
        } else {
3448 3449
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3450
        }
P
pbrook 已提交
3451
        tcg_temp_free_i32(temp);
3452
    }
3453
    if (type == BCOND_IM) {
3454 3455 3456 3457 3458 3459
        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 已提交
3460
        gen_set_label(l1);
3461
        gen_goto_tb(ctx, 1, ctx->nip);
3462
    } else {
3463
#if defined(TARGET_PPC64)
3464 3465 3466 3467 3468 3469 3470 3471 3472 3473
        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);
3474 3475
        else
#endif
3476
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
B
bellard 已提交
3477
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3478
    }
3479 3480
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

B
bellard 已提交
3663
/***                          Processor control                            ***/
B
Blue Swirl 已提交
3664

3665
/* mcrxr */
B
Blue Swirl 已提交
3666
static void gen_mcrxr(DisasContext *ctx)
B
bellard 已提交
3667
{
A
aurel32 已提交
3668 3669
    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);
3670
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
B
bellard 已提交
3671 3672
}

A
aurel32 已提交
3673
/* mfcr mfocrf */
B
Blue Swirl 已提交
3674
static void gen_mfcr(DisasContext *ctx)
B
bellard 已提交
3675
{
3676
    uint32_t crm, crn;
3677

3678 3679
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3680
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3681
            crn = ctz32 (crm);
3682
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3683 3684
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3685
        }
3686
    } else {
A
aurel32 已提交
3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704
        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);
3705
    }
B
bellard 已提交
3706 3707 3708
}

/* mfmsr */
B
Blue Swirl 已提交
3709
static void gen_mfmsr(DisasContext *ctx)
B
bellard 已提交
3710
{
3711
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3712
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3713
#else
A
aurel32 已提交
3714
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3715
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3716
        return;
3717
    }
3718
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3719
#endif
B
bellard 已提交
3720 3721
}

J
j_mayer 已提交
3722
#if 1
3723
#define SPR_NOACCESS ((void *)(-1UL))
3724 3725 3726 3727 3728 3729 3730 3731 3732
#else
static void spr_noaccess (void *opaque, int sprn)
{
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
}
#define SPR_NOACCESS (&spr_noaccess)
#endif

B
bellard 已提交
3733
/* mfspr */
B
Blue Swirl 已提交
3734
static inline void gen_op_mfspr(DisasContext *ctx)
B
bellard 已提交
3735
{
A
aurel32 已提交
3736
    void (*read_cb)(void *opaque, int gprn, int sprn);
B
bellard 已提交
3737 3738
    uint32_t sprn = SPR(ctx->opcode);

3739
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3740
    if (ctx->mem_idx == 2)
3741
        read_cb = ctx->spr_cb[sprn].hea_read;
A
aurel32 已提交
3742
    else if (ctx->mem_idx)
3743 3744
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3745
#endif
3746
        read_cb = ctx->spr_cb[sprn].uea_read;
3747 3748
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3749
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3750 3751
        } else {
            /* Privilege exception */
3752 3753 3754 3755 3756
            /* 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) {
3757
                qemu_log("Trying to read privileged spr %d %03x at "
3758 3759 3760
                         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);
3761
            }
A
aurel32 已提交
3762
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
3763
        }
3764 3765
    } else {
        /* Not defined */
3766
        qemu_log("Trying to read invalid spr %d %03x at "
3767 3768
                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3769
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3770
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3771 3772 3773
    }
}

B
Blue Swirl 已提交
3774
static void gen_mfspr(DisasContext *ctx)
B
bellard 已提交
3775
{
3776
    gen_op_mfspr(ctx);
3777
}
3778 3779

/* mftb */
B
Blue Swirl 已提交
3780
static void gen_mftb(DisasContext *ctx)
3781 3782
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3783 3784
}

A
aurel32 已提交
3785
/* mtcrf mtocrf*/
B
Blue Swirl 已提交
3786
static void gen_mtcrf(DisasContext *ctx)
B
bellard 已提交
3787
{
3788
    uint32_t crm, crn;
3789

3790
    crm = CRM(ctx->opcode);
M
malc 已提交
3791 3792 3793
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
3794
            crn = ctz32 (crm);
M
malc 已提交
3795
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
3796 3797
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
3798 3799
            tcg_temp_free_i32(temp);
        }
3800
    } else {
A
aurel32 已提交
3801 3802 3803 3804 3805 3806 3807 3808
        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 已提交
3809
        tcg_temp_free_i32(temp);
3810
    }
B
bellard 已提交
3811 3812 3813
}

/* mtmsr */
J
j_mayer 已提交
3814
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3815
static void gen_mtmsrd(DisasContext *ctx)
J
j_mayer 已提交
3816 3817
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3818
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3819
#else
A
aurel32 已提交
3820
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3821
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3822 3823
        return;
    }
3824 3825
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3826 3827 3828 3829 3830
        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);
3831
    } else {
3832 3833 3834 3835
        /* 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
         */
3836
        gen_update_nip(ctx, ctx->nip);
3837
        gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3838 3839
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3840
        gen_stop_exception(ctx);
3841
    }
J
j_mayer 已提交
3842 3843 3844 3845
#endif
}
#endif

B
Blue Swirl 已提交
3846
static void gen_mtmsr(DisasContext *ctx)
B
bellard 已提交
3847
{
3848
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3849
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3850
#else
A
aurel32 已提交
3851
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3852
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3853
        return;
3854
    }
3855 3856
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3857 3858 3859 3860 3861
        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);
3862
    } else {
3863 3864 3865 3866
        /* 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
         */
3867
        gen_update_nip(ctx, ctx->nip);
3868
#if defined(TARGET_PPC64)
3869 3870 3871 3872 3873 3874 3875 3876 3877 3878
        if (!ctx->sf_mode) {
            TCGv t0 = tcg_temp_new();
            TCGv t1 = tcg_temp_new();
            tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
            tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
            tcg_gen_or_tl(t0, t0, t1);
            tcg_temp_free(t1);
            gen_helper_store_msr(t0);
            tcg_temp_free(t0);
        } else
3879
#endif
3880
            gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3881
        /* Must stop the translation as machine state (may have) changed */
3882
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3883
        gen_stop_exception(ctx);
3884
    }
3885
#endif
B
bellard 已提交
3886 3887 3888
}

/* mtspr */
B
Blue Swirl 已提交
3889
static void gen_mtspr(DisasContext *ctx)
B
bellard 已提交
3890
{
A
aurel32 已提交
3891
    void (*write_cb)(void *opaque, int sprn, int gprn);
B
bellard 已提交
3892 3893
    uint32_t sprn = SPR(ctx->opcode);

3894
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3895
    if (ctx->mem_idx == 2)
3896
        write_cb = ctx->spr_cb[sprn].hea_write;
A
aurel32 已提交
3897
    else if (ctx->mem_idx)
3898 3899
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
3900
#endif
3901
        write_cb = ctx->spr_cb[sprn].uea_write;
3902 3903
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3904
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
3905 3906
        } else {
            /* Privilege exception */
3907
            qemu_log("Trying to write privileged spr %d %03x at "
3908 3909 3910
                     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 已提交
3911
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3912
        }
3913 3914
    } else {
        /* Not defined */
3915
        qemu_log("Trying to write invalid spr %d %03x at "
3916 3917
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3918
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3919
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3920 3921 3922 3923
    }
}

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

3925
/* dcbf */
B
Blue Swirl 已提交
3926
static void gen_dcbf(DisasContext *ctx)
B
bellard 已提交
3927
{
J
j_mayer 已提交
3928
    /* XXX: specification says this is treated as a load by the MMU */
A
aurel32 已提交
3929 3930 3931 3932 3933
    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);
3934
    tcg_temp_free(t0);
B
bellard 已提交
3935 3936 3937
}

/* dcbi (Supervisor only) */
B
Blue Swirl 已提交
3938
static void gen_dcbi(DisasContext *ctx)
B
bellard 已提交
3939
{
3940
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3941
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3942
#else
A
aurel32 已提交
3943
    TCGv EA, val;
A
aurel32 已提交
3944
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3945
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3946
        return;
3947
    }
P
pbrook 已提交
3948
    EA = tcg_temp_new();
A
aurel32 已提交
3949 3950
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
3951
    val = tcg_temp_new();
3952
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
3953 3954
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
3955 3956
    tcg_temp_free(val);
    tcg_temp_free(EA);
3957
#endif
B
bellard 已提交
3958 3959 3960
}

/* dcdst */
B
Blue Swirl 已提交
3961
static void gen_dcbst(DisasContext *ctx)
B
bellard 已提交
3962
{
3963
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
3964 3965 3966 3967 3968
    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);
3969
    tcg_temp_free(t0);
B
bellard 已提交
3970 3971 3972
}

/* dcbt */
B
Blue Swirl 已提交
3973
static void gen_dcbt(DisasContext *ctx)
B
bellard 已提交
3974
{
3975
    /* interpreted as no-op */
3976 3977 3978
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
3979 3980 3981
}

/* dcbtst */
B
Blue Swirl 已提交
3982
static void gen_dcbtst(DisasContext *ctx)
B
bellard 已提交
3983
{
3984
    /* interpreted as no-op */
3985 3986 3987
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
3988 3989 3990
}

/* dcbz */
B
Blue Swirl 已提交
3991
static void gen_dcbz(DisasContext *ctx)
B
bellard 已提交
3992
{
A
aurel32 已提交
3993 3994
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
3995 3996
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3997 3998
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
3999 4000
    gen_helper_dcbz(t0);
    tcg_temp_free(t0);
4001 4002
}

B
Blue Swirl 已提交
4003
static void gen_dcbz_970(DisasContext *ctx)
4004
{
A
aurel32 已提交
4005 4006
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4007 4008
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4009 4010
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4011
    if (ctx->opcode & 0x00200000)
4012
        gen_helper_dcbz(t0);
4013
    else
4014 4015
        gen_helper_dcbz_970(t0);
    tcg_temp_free(t0);
B
bellard 已提交
4016 4017
}

4018
/* dst / dstt */
B
Blue Swirl 已提交
4019
static void gen_dst(DisasContext *ctx)
4020 4021 4022 4023 4024 4025 4026 4027 4028
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }
}

/* dstst /dststt */
B
Blue Swirl 已提交
4029
static void gen_dstst(DisasContext *ctx)
4030 4031 4032 4033 4034 4035 4036 4037 4038 4039
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }

}

/* dss / dssall */
B
Blue Swirl 已提交
4040
static void gen_dss(DisasContext *ctx)
4041 4042 4043 4044
{
    /* interpreted as no-op */
}

B
bellard 已提交
4045
/* icbi */
B
Blue Swirl 已提交
4046
static void gen_icbi(DisasContext *ctx)
B
bellard 已提交
4047
{
A
aurel32 已提交
4048 4049
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4050 4051
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4052 4053
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4054 4055
    gen_helper_icbi(t0);
    tcg_temp_free(t0);
B
bellard 已提交
4056 4057 4058 4059
}

/* Optional: */
/* dcba */
B
Blue Swirl 已提交
4060
static void gen_dcba(DisasContext *ctx)
B
bellard 已提交
4061
{
4062 4063 4064 4065
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4066 4067 4068 4069
}

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

4071
/* mfsr */
B
Blue Swirl 已提交
4072
static void gen_mfsr(DisasContext *ctx)
B
bellard 已提交
4073
{
4074
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4075
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4076
#else
4077
    TCGv t0;
A
aurel32 已提交
4078
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4079
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4080
        return;
4081
    }
4082 4083 4084
    t0 = tcg_const_tl(SR(ctx->opcode));
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
4085
#endif
B
bellard 已提交
4086 4087 4088
}

/* mfsrin */
B
Blue Swirl 已提交
4089
static void gen_mfsrin(DisasContext *ctx)
B
bellard 已提交
4090
{
4091
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4092
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4093
#else
4094
    TCGv t0;
A
aurel32 已提交
4095
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4096
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4097
        return;
4098
    }
4099 4100 4101 4102 4103
    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);
4104
#endif
B
bellard 已提交
4105 4106 4107
}

/* mtsr */
B
Blue Swirl 已提交
4108
static void gen_mtsr(DisasContext *ctx)
B
bellard 已提交
4109
{
4110
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4111
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4112
#else
4113
    TCGv t0;
A
aurel32 已提交
4114
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4115
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4116
        return;
4117
    }
4118 4119 4120
    t0 = tcg_const_tl(SR(ctx->opcode));
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
    tcg_temp_free(t0);
4121
#endif
B
bellard 已提交
4122 4123 4124
}

/* mtsrin */
B
Blue Swirl 已提交
4125
static void gen_mtsrin(DisasContext *ctx)
B
bellard 已提交
4126
{
4127
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4128
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4129
#else
4130
    TCGv t0;
A
aurel32 已提交
4131
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4132
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4133
        return;
4134
    }
4135 4136 4137 4138 4139
    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);
4140
#endif
B
bellard 已提交
4141 4142
}

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

4146
/* mfsr */
B
Blue Swirl 已提交
4147
static void gen_mfsr_64b(DisasContext *ctx)
4148 4149
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4150
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4151
#else
4152
    TCGv t0;
A
aurel32 已提交
4153
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4154
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4155 4156
        return;
    }
4157
    t0 = tcg_const_tl(SR(ctx->opcode));
B
blueswir1 已提交
4158
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4159
    tcg_temp_free(t0);
4160 4161 4162 4163
#endif
}

/* mfsrin */
B
Blue Swirl 已提交
4164
static void gen_mfsrin_64b(DisasContext *ctx)
4165 4166
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4167
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4168
#else
4169
    TCGv t0;
A
aurel32 已提交
4170
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4171
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4172 4173
        return;
    }
4174 4175 4176
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
B
blueswir1 已提交
4177
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4178
    tcg_temp_free(t0);
4179 4180 4181 4182
#endif
}

/* mtsr */
B
Blue Swirl 已提交
4183
static void gen_mtsr_64b(DisasContext *ctx)
4184 4185
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4186
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4187
#else
4188
    TCGv t0;
A
aurel32 已提交
4189
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4190
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4191 4192
        return;
    }
4193
    t0 = tcg_const_tl(SR(ctx->opcode));
B
blueswir1 已提交
4194
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4195
    tcg_temp_free(t0);
4196 4197 4198 4199
#endif
}

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

/* slbmte */
B
Blue Swirl 已提交
4219
static void gen_slbmte(DisasContext *ctx)
B
blueswir1 已提交
4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231
{
#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
}

4232 4233
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4234
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4235
/* Optional & mem_idx only: */
B
Blue Swirl 已提交
4236

4237
/* tlbia */
B
Blue Swirl 已提交
4238
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4239
{
4240
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4241
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4242
#else
A
aurel32 已提交
4243
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4244
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4245
        return;
4246
    }
4247
    gen_helper_tlbia();
4248
#endif
B
bellard 已提交
4249 4250
}

B
blueswir1 已提交
4251
/* tlbiel */
B
Blue Swirl 已提交
4252
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264
{
#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 已提交
4265
/* tlbie */
B
Blue Swirl 已提交
4266
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4267
{
4268
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4269
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4270
#else
A
aurel32 已提交
4271
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4272
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4273
        return;
4274
    }
4275
#if defined(TARGET_PPC64)
4276 4277 4278 4279 4280 4281
    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
4282
#endif
4283
        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4284
#endif
B
bellard 已提交
4285 4286 4287
}

/* tlbsync */
B
Blue Swirl 已提交
4288
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4289
{
4290
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4291
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4292
#else
A
aurel32 已提交
4293
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4294
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4295
        return;
4296 4297 4298 4299
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4300
    gen_stop_exception(ctx);
4301
#endif
B
bellard 已提交
4302 4303
}

J
j_mayer 已提交
4304 4305
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4306
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4307 4308
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4309
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4310
#else
A
aurel32 已提交
4311
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4312
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4313 4314
        return;
    }
4315
    gen_helper_slbia();
J
j_mayer 已提交
4316 4317 4318 4319
#endif
}

/* slbie */
B
Blue Swirl 已提交
4320
static void gen_slbie(DisasContext *ctx)
J
j_mayer 已提交
4321 4322
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4323
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4324
#else
A
aurel32 已提交
4325
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4326
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4327 4328
        return;
    }
4329
    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4330 4331 4332 4333
#endif
}
#endif

B
bellard 已提交
4334 4335
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4336

4337
/* eciwx */
B
Blue Swirl 已提交
4338
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4339
{
A
aurel32 已提交
4340
    TCGv t0;
4341
    /* Should check EAR[E] ! */
A
aurel32 已提交
4342 4343 4344
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4345
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4346
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4347
    tcg_temp_free(t0);
4348 4349 4350
}

/* ecowx */
B
Blue Swirl 已提交
4351
static void gen_ecowx(DisasContext *ctx)
4352
{
A
aurel32 已提交
4353
    TCGv t0;
4354
    /* Should check EAR[E] ! */
A
aurel32 已提交
4355 4356 4357
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4358
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4359
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4360
    tcg_temp_free(t0);
4361 4362 4363
}

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

4365
/* abs - abs. */
B
Blue Swirl 已提交
4366
static void gen_abs(DisasContext *ctx)
4367
{
4368 4369 4370 4371 4372 4373 4374 4375
    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);
4376
    if (unlikely(Rc(ctx->opcode) != 0))
4377
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4378 4379 4380
}

/* abso - abso. */
B
Blue Swirl 已提交
4381
static void gen_abso(DisasContext *ctx)
4382
{
4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397
    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);
4398
    if (unlikely(Rc(ctx->opcode) != 0))
4399
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4400 4401 4402
}

/* clcs */
B
Blue Swirl 已提交
4403
static void gen_clcs(DisasContext *ctx)
4404
{
4405 4406 4407
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
4408
    /* Rc=1 sets CR0 to an undefined state */
4409 4410 4411
}

/* div - div. */
B
Blue Swirl 已提交
4412
static void gen_div(DisasContext *ctx)
4413
{
4414
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4415
    if (unlikely(Rc(ctx->opcode) != 0))
4416
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4417 4418 4419
}

/* divo - divo. */
B
Blue Swirl 已提交
4420
static void gen_divo(DisasContext *ctx)
4421
{
4422
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4423
    if (unlikely(Rc(ctx->opcode) != 0))
4424
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4425 4426 4427
}

/* divs - divs. */
B
Blue Swirl 已提交
4428
static void gen_divs(DisasContext *ctx)
4429
{
4430
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4431
    if (unlikely(Rc(ctx->opcode) != 0))
4432
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4433 4434 4435
}

/* divso - divso. */
B
Blue Swirl 已提交
4436
static void gen_divso(DisasContext *ctx)
4437
{
4438
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4439
    if (unlikely(Rc(ctx->opcode) != 0))
4440
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4441 4442 4443
}

/* doz - doz. */
B
Blue Swirl 已提交
4444
static void gen_doz(DisasContext *ctx)
4445
{
4446 4447 4448 4449 4450 4451 4452 4453
    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);
4454
    if (unlikely(Rc(ctx->opcode) != 0))
4455
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4456 4457 4458
}

/* dozo - dozo. */
B
Blue Swirl 已提交
4459
static void gen_dozo(DisasContext *ctx)
4460
{
4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482
    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);
4483
    if (unlikely(Rc(ctx->opcode) != 0))
4484
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4485 4486 4487
}

/* dozi */
B
Blue Swirl 已提交
4488
static void gen_dozi(DisasContext *ctx)
4489
{
4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500
    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)]);
4501 4502 4503
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4504
static void gen_lscbx(DisasContext *ctx)
4505
{
4506 4507 4508 4509
    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));
4510

A
aurel32 已提交
4511
    gen_addr_reg_index(ctx, t0);
4512
    /* NIP cannot be restored if the memory exception comes from an helper */
4513
    gen_update_nip(ctx, ctx->nip - 4);
4514 4515 4516 4517
    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 已提交
4518
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4519
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4520
    if (unlikely(Rc(ctx->opcode) != 0))
4521 4522
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4523 4524 4525
}

/* maskg - maskg. */
B
Blue Swirl 已提交
4526
static void gen_maskg(DisasContext *ctx)
4527
{
4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546
    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);
4547
    if (unlikely(Rc(ctx->opcode) != 0))
4548
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4549 4550 4551
}

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

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

/* mulo - mulo. */
B
Blue Swirl 已提交
4586
static void gen_mulo(DisasContext *ctx)
4587
{
4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607
    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);
4608
    if (unlikely(Rc(ctx->opcode) != 0))
4609
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4610 4611 4612
}

/* nabs - nabs. */
B
Blue Swirl 已提交
4613
static void gen_nabs(DisasContext *ctx)
4614
{
4615 4616 4617 4618 4619 4620 4621 4622
    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);
4623
    if (unlikely(Rc(ctx->opcode) != 0))
4624
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4625 4626 4627
}

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

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

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

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

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

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

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

/* sllq - sllq. */
B
Blue Swirl 已提交
4754
static void gen_sllq(DisasContext *ctx)
4755
{
4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777
    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);
4778
    if (unlikely(Rc(ctx->opcode) != 0))
4779
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4780 4781 4782
}

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

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

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

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

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

/* sreq */
B
Blue Swirl 已提交
4895
static void gen_sreq(DisasContext *ctx)
4896
{
4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911
    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);
4912
    if (unlikely(Rc(ctx->opcode) != 0))
4913
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4914 4915 4916
}

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

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

/* srlq */
B
Blue Swirl 已提交
4952
static void gen_srlq(DisasContext *ctx)
4953
{
4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976
    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);
4977
    if (unlikely(Rc(ctx->opcode) != 0))
4978
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4979 4980 4981
}

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

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

5006
/* dsa  */
B
Blue Swirl 已提交
5007
static void gen_dsa(DisasContext *ctx)
5008 5009
{
    /* XXX: TODO */
A
aurel32 已提交
5010
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5011 5012 5013
}

/* esa */
B
Blue Swirl 已提交
5014
static void gen_esa(DisasContext *ctx)
5015 5016
{
    /* XXX: TODO */
A
aurel32 已提交
5017
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5018 5019 5020
}

/* mfrom */
B
Blue Swirl 已提交
5021
static void gen_mfrom(DisasContext *ctx)
5022 5023
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5024
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5025
#else
A
aurel32 已提交
5026
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5027
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5028 5029
        return;
    }
5030
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5031 5032 5033 5034
#endif
}

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

5036
/* tlbld */
B
Blue Swirl 已提交
5037
static void gen_tlbld_6xx(DisasContext *ctx)
5038 5039
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5040
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5041
#else
A
aurel32 已提交
5042
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5043
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5044 5045
        return;
    }
5046
    gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5047 5048 5049 5050
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5051
static void gen_tlbli_6xx(DisasContext *ctx)
5052 5053
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5054
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5055
#else
A
aurel32 已提交
5056
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5057
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5058 5059
        return;
    }
5060
    gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5061 5062 5063
#endif
}

5064
/* 74xx TLB management */
B
Blue Swirl 已提交
5065

5066
/* tlbld */
B
Blue Swirl 已提交
5067
static void gen_tlbld_74xx(DisasContext *ctx)
5068 5069
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5070
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5071
#else
A
aurel32 已提交
5072
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5073
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5074 5075
        return;
    }
5076
    gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5077 5078 5079 5080
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5081
static void gen_tlbli_74xx(DisasContext *ctx)
5082 5083
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5084
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5085
#else
A
aurel32 已提交
5086
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5087
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5088 5089
        return;
    }
5090
    gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5091 5092 5093
#endif
}

5094
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5095

5096
/* clf */
B
Blue Swirl 已提交
5097
static void gen_clf(DisasContext *ctx)
5098 5099 5100 5101 5102
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5103
static void gen_cli(DisasContext *ctx)
5104
{
B
blueswir1 已提交
5105
    /* Cache line invalidate: privileged and treated as no-op */
5106
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5107
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5108
#else
A
aurel32 已提交
5109
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5110
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5111 5112 5113 5114 5115 5116
        return;
    }
#endif
}

/* dclst */
B
Blue Swirl 已提交
5117
static void gen_dclst(DisasContext *ctx)
5118 5119 5120 5121
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5122
static void gen_mfsri(DisasContext *ctx)
5123 5124
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5125
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5126
#else
5127 5128 5129
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5130
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5131
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5132 5133
        return;
    }
5134
    t0 = tcg_temp_new();
A
aurel32 已提交
5135
    gen_addr_reg_index(ctx, t0);
5136 5137 5138 5139
    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);
5140
    if (ra != 0 && ra != rd)
5141
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5142 5143 5144
#endif
}

B
Blue Swirl 已提交
5145
static void gen_rac(DisasContext *ctx)
5146 5147
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5148
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5149
#else
5150
    TCGv t0;
A
aurel32 已提交
5151
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5152
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5153 5154
        return;
    }
5155
    t0 = tcg_temp_new();
A
aurel32 已提交
5156
    gen_addr_reg_index(ctx, t0);
5157 5158
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
5159 5160 5161
#endif
}

B
Blue Swirl 已提交
5162
static void gen_rfsvc(DisasContext *ctx)
5163 5164
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5165
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5166
#else
A
aurel32 已提交
5167
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5168
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5169 5170
        return;
    }
5171
    gen_helper_rfsvc();
A
aurel32 已提交
5172
    gen_sync_exception(ctx);
5173 5174 5175 5176 5177 5178 5179 5180 5181
#endif
}

/* svc is not implemented for now */

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

/* lfq */
B
Blue Swirl 已提交
5182
static void gen_lfq(DisasContext *ctx)
5183
{
5184
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5185 5186 5187 5188 5189 5190 5191
    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);
5192
    tcg_temp_free(t0);
5193 5194 5195
}

/* lfqu */
B
Blue Swirl 已提交
5196
static void gen_lfqu(DisasContext *ctx)
5197 5198
{
    int ra = rA(ctx->opcode);
5199
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5200 5201 5202 5203 5204 5205 5206 5207
    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);
5208
    if (ra != 0)
5209 5210 5211
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5212 5213 5214
}

/* lfqux */
B
Blue Swirl 已提交
5215
static void gen_lfqux(DisasContext *ctx)
5216 5217
{
    int ra = rA(ctx->opcode);
5218
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5219 5220 5221 5222 5223 5224 5225 5226 5227
    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);
5228
    if (ra != 0)
5229 5230
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5231 5232 5233
}

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

/* stfq */
B
Blue Swirl 已提交
5248
static void gen_stfq(DisasContext *ctx)
5249
{
5250
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5251 5252 5253 5254 5255 5256 5257
    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);
5258
    tcg_temp_free(t0);
5259 5260 5261
}

/* stfqu */
B
Blue Swirl 已提交
5262
static void gen_stfqu(DisasContext *ctx)
5263 5264
{
    int ra = rA(ctx->opcode);
5265
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5266 5267 5268 5269 5270 5271 5272 5273 5274
    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);
5275
    if (ra != 0)
5276 5277
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5278 5279 5280
}

/* stfqux */
B
Blue Swirl 已提交
5281
static void gen_stfqux(DisasContext *ctx)
5282 5283
{
    int ra = rA(ctx->opcode);
5284
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5285 5286 5287 5288 5289 5290 5291 5292 5293
    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);
5294
    if (ra != 0)
5295 5296
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5297 5298 5299
}

/* stfqx */
B
Blue Swirl 已提交
5300
static void gen_stfqx(DisasContext *ctx)
5301
{
5302
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5303 5304 5305 5306 5307 5308 5309
    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);
5310
    tcg_temp_free(t0);
5311 5312 5313
}

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

5315
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5316
static void gen_mfapidi(DisasContext *ctx)
5317 5318
{
    /* XXX: TODO */
A
aurel32 已提交
5319
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5320 5321
}

5322
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5323
static void gen_tlbiva(DisasContext *ctx)
5324 5325
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5326
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5327
#else
5328
    TCGv t0;
A
aurel32 已提交
5329
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5330
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5331 5332
        return;
    }
5333
    t0 = tcg_temp_new();
A
aurel32 已提交
5334
    gen_addr_reg_index(ctx, t0);
5335 5336
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(t0);
5337 5338 5339 5340
#endif
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5341 5342
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5343
{
5344 5345
    TCGv t0, t1;

P
pbrook 已提交
5346 5347
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5348

5349 5350 5351 5352 5353 5354 5355
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5356 5357 5358
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5359 5360 5361 5362 5363
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5364 5365 5366
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5367 5368 5369 5370 5371 5372 5373
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5374 5375 5376 5377
        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);
5378 5379 5380 5381 5382
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5383 5384 5385 5386
        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);
5387 5388 5389 5390 5391 5392 5393
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5394 5395
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5396 5397 5398 5399 5400
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5401 5402
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5403 5404 5405
        break;
    }
    if (opc2 & 0x04) {
5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429
        /* (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 已提交
5430
                if (opc3 & 0x02) {
5431 5432 5433 5434 5435 5436 5437
                    /* 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 已提交
5438
                if (opc3 & 0x02) {
5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451
                    /* 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);
5452
    }
5453 5454
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5455 5456
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5457
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5458 5459 5460
    }
}

5461
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5462
static void glue(gen_, name)(DisasContext *ctx)                               \
5463 5464 5465 5466 5467 5468
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5469
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5470
/* macchwo   - macchwo.   */
5471
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5472
/* macchws   - macchws.   */
5473
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5474
/* macchwso  - macchwso.  */
5475
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5476
/* macchwsu  - macchwsu.  */
5477
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5478
/* macchwsuo - macchwsuo. */
5479
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5480
/* macchwu   - macchwu.   */
5481
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5482
/* macchwuo  - macchwuo.  */
5483
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5484
/* machhw    - machhw.    */
5485
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5486
/* machhwo   - machhwo.   */
5487
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5488
/* machhws   - machhws.   */
5489
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5490
/* machhwso  - machhwso.  */
5491
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5492
/* machhwsu  - machhwsu.  */
5493
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5494
/* machhwsuo - machhwsuo. */
5495
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5496
/* machhwu   - machhwu.   */
5497
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5498
/* machhwuo  - machhwuo.  */
5499
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5500
/* maclhw    - maclhw.    */
5501
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5502
/* maclhwo   - maclhwo.   */
5503
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5504
/* maclhws   - maclhws.   */
5505
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5506
/* maclhwso  - maclhwso.  */
5507
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5508
/* maclhwu   - maclhwu.   */
5509
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5510
/* maclhwuo  - maclhwuo.  */
5511
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5512
/* maclhwsu  - maclhwsu.  */
5513
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5514
/* maclhwsuo - maclhwsuo. */
5515
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5516
/* nmacchw   - nmacchw.   */
5517
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5518
/* nmacchwo  - nmacchwo.  */
5519
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5520
/* nmacchws  - nmacchws.  */
5521
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5522
/* nmacchwso - nmacchwso. */
5523
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5524
/* nmachhw   - nmachhw.   */
5525
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5526
/* nmachhwo  - nmachhwo.  */
5527
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5528
/* nmachhws  - nmachhws.  */
5529
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5530
/* nmachhwso - nmachhwso. */
5531
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5532
/* nmaclhw   - nmaclhw.   */
5533
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5534
/* nmaclhwo  - nmaclhwo.  */
5535
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5536
/* nmaclhws  - nmaclhws.  */
5537
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5538
/* nmaclhwso - nmaclhwso. */
5539
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5540 5541

/* mulchw  - mulchw.  */
5542
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5543
/* mulchwu - mulchwu. */
5544
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5545
/* mulhhw  - mulhhw.  */
5546
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5547
/* mulhhwu - mulhhwu. */
5548
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5549
/* mullhw  - mullhw.  */
5550
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5551
/* mullhwu - mullhwu. */
5552
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5553 5554

/* mfdcr */
B
Blue Swirl 已提交
5555
static void gen_mfdcr(DisasContext *ctx)
5556 5557
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5558
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5559
#else
5560
    TCGv dcrn;
A
aurel32 已提交
5561
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5562
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5563 5564
        return;
    }
5565 5566 5567 5568 5569
    /* 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);
5570 5571 5572 5573
#endif
}

/* mtdcr */
B
Blue Swirl 已提交
5574
static void gen_mtdcr(DisasContext *ctx)
5575 5576
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5577
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5578
#else
5579
    TCGv dcrn;
A
aurel32 已提交
5580
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5581
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5582 5583
        return;
    }
5584 5585 5586 5587 5588
    /* 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);
5589 5590 5591 5592
#endif
}

/* mfdcrx */
5593
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5594
static void gen_mfdcrx(DisasContext *ctx)
5595 5596
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5597
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5598
#else
A
aurel32 已提交
5599
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5600
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5601 5602
        return;
    }
5603 5604 5605
    /* 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)]);
5606
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5607 5608 5609 5610
#endif
}

/* mtdcrx */
5611
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5612
static void gen_mtdcrx(DisasContext *ctx)
5613 5614
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5615
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5616
#else
A
aurel32 已提交
5617
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5618
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5619 5620
        return;
    }
5621 5622 5623
    /* 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)]);
5624
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5625 5626 5627
#endif
}

5628
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5629
static void gen_mfdcrux(DisasContext *ctx)
5630
{
5631 5632 5633
    /* 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)]);
5634 5635 5636 5637
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5638
static void gen_mtdcrux(DisasContext *ctx)
5639
{
5640 5641 5642
    /* 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)]);
5643 5644 5645
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5646
/* dccci */
B
Blue Swirl 已提交
5647
static void gen_dccci(DisasContext *ctx)
5648 5649
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5650
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5651
#else
A
aurel32 已提交
5652
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5653
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5654 5655 5656 5657 5658 5659 5660
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
B
Blue Swirl 已提交
5661
static void gen_dcread(DisasContext *ctx)
5662 5663
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5664
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5665
#else
A
aurel32 已提交
5666
    TCGv EA, val;
A
aurel32 已提交
5667
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5668
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5669 5670
        return;
    }
A
aurel32 已提交
5671
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5672
    EA = tcg_temp_new();
A
aurel32 已提交
5673
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5674
    val = tcg_temp_new();
A
aurel32 已提交
5675
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5676 5677 5678
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5679 5680 5681 5682
#endif
}

/* icbt */
B
Blue Swirl 已提交
5683
static void gen_icbt_40x(DisasContext *ctx)
5684 5685 5686 5687 5688 5689 5690 5691
{
    /* 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 已提交
5692
static void gen_iccci(DisasContext *ctx)
5693 5694
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5695
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5696
#else
A
aurel32 已提交
5697
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5698
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5699 5700 5701 5702 5703 5704 5705
        return;
    }
    /* interpreted as no-op */
#endif
}

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

A
aurel32 已提交
5719
/* rfci (mem_idx only) */
B
Blue Swirl 已提交
5720
static void gen_rfci_40x(DisasContext *ctx)
5721 5722
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5723
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5724
#else
A
aurel32 已提交
5725
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5726
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5727 5728 5729
        return;
    }
    /* Restore CPU state */
5730
    gen_helper_40x_rfci();
A
aurel32 已提交
5731
    gen_sync_exception(ctx);
5732 5733 5734
#endif
}

B
Blue Swirl 已提交
5735
static void gen_rfci(DisasContext *ctx)
5736 5737
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5738
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5739
#else
A
aurel32 已提交
5740
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5741
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5742 5743 5744
        return;
    }
    /* Restore CPU state */
5745
    gen_helper_rfci();
A
aurel32 已提交
5746
    gen_sync_exception(ctx);
5747 5748 5749 5750
#endif
}

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

5752
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5753
static void gen_rfdi(DisasContext *ctx)
5754 5755
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5756
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5757
#else
A
aurel32 已提交
5758
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5759
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5760 5761 5762
        return;
    }
    /* Restore CPU state */
5763
    gen_helper_rfdi();
A
aurel32 已提交
5764
    gen_sync_exception(ctx);
5765 5766 5767
#endif
}

5768
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5769
static void gen_rfmci(DisasContext *ctx)
5770 5771
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5772
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5773
#else
A
aurel32 已提交
5774
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5775
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5776 5777 5778
        return;
    }
    /* Restore CPU state */
5779
    gen_helper_rfmci();
A
aurel32 已提交
5780
    gen_sync_exception(ctx);
5781 5782
#endif
}
5783

5784
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5785

5786
/* tlbre */
B
Blue Swirl 已提交
5787
static void gen_tlbre_40x(DisasContext *ctx)
5788 5789
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5790
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5791
#else
A
aurel32 已提交
5792
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5793
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5794 5795 5796 5797
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5798
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5799 5800
        break;
    case 1:
5801
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5802 5803
        break;
    default:
A
aurel32 已提交
5804
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5805
        break;
5806
    }
5807 5808 5809
#endif
}

5810
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5811
static void gen_tlbsx_40x(DisasContext *ctx)
5812 5813
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5814
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5815
#else
5816
    TCGv t0;
A
aurel32 已提交
5817
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5818
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5819 5820
        return;
    }
5821
    t0 = tcg_temp_new();
A
aurel32 已提交
5822
    gen_addr_reg_index(ctx, t0);
5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833
    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);
    }
5834
#endif
B
bellard 已提交
5835 5836
}

5837
/* tlbwe */
B
Blue Swirl 已提交
5838
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
5839
{
5840
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5841
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5842
#else
A
aurel32 已提交
5843
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5844
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5845 5846 5847 5848
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5849
        gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5850 5851
        break;
    case 1:
5852
        gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5853 5854
        break;
    default:
A
aurel32 已提交
5855
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5856
        break;
5857
    }
5858 5859 5860
#endif
}

5861
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
5862

5863
/* tlbre */
B
Blue Swirl 已提交
5864
static void gen_tlbre_440(DisasContext *ctx)
5865 5866
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5867
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5868
#else
A
aurel32 已提交
5869
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5870
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5871 5872 5873 5874 5875 5876
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5877 5878 5879 5880 5881
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
            gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
            tcg_temp_free_i32(t0);
        }
5882 5883
        break;
    default:
A
aurel32 已提交
5884
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5885 5886 5887 5888 5889 5890
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5891
static void gen_tlbsx_440(DisasContext *ctx)
5892 5893
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5894
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5895
#else
5896
    TCGv t0;
A
aurel32 已提交
5897
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5898
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5899 5900
        return;
    }
5901
    t0 = tcg_temp_new();
A
aurel32 已提交
5902
    gen_addr_reg_index(ctx, t0);
5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913
    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);
    }
5914 5915 5916 5917
#endif
}

/* tlbwe */
B
Blue Swirl 已提交
5918
static void gen_tlbwe_440(DisasContext *ctx)
5919 5920
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5921
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5922
#else
A
aurel32 已提交
5923
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5924
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5925 5926 5927 5928 5929 5930
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5931 5932 5933 5934 5935
        {
            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);
        }
5936 5937
        break;
    default:
A
aurel32 已提交
5938
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5939 5940 5941 5942 5943
        break;
    }
#endif
}

5944
/* wrtee */
B
Blue Swirl 已提交
5945
static void gen_wrtee(DisasContext *ctx)
5946 5947
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5948
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5949
#else
5950
    TCGv t0;
A
aurel32 已提交
5951
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5952
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5953 5954
        return;
    }
5955 5956 5957 5958 5959
    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 已提交
5960 5961 5962
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
5963
    gen_stop_exception(ctx);
5964 5965 5966 5967
#endif
}

/* wrteei */
B
Blue Swirl 已提交
5968
static void gen_wrteei(DisasContext *ctx)
5969 5970
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5971
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5972
#else
A
aurel32 已提交
5973
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5974
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5975 5976
        return;
    }
5977
    if (ctx->opcode & 0x00008000) {
5978 5979
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
5980
        gen_stop_exception(ctx);
5981
    } else {
A
aurel32 已提交
5982
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
5983
    }
5984 5985 5986
#endif
}

J
j_mayer 已提交
5987
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
5988

5989
/* dlmzb */
B
Blue Swirl 已提交
5990
static void gen_dlmzb(DisasContext *ctx)
5991
{
5992 5993 5994 5995
    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);
5996 5997 5998
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
5999
static void gen_mbar(DisasContext *ctx)
6000 6001 6002 6003 6004
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
B
Blue Swirl 已提交
6005
static void gen_msync(DisasContext *ctx)
6006 6007 6008 6009 6010
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6011
static void gen_icbt_440(DisasContext *ctx)
6012 6013 6014 6015 6016
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6017 6018
}

6019 6020 6021
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

B
Blue Swirl 已提交
6022
static inline TCGv_ptr gen_avr_ptr(int reg)
A
aurel32 已提交
6023
{
A
aurel32 已提交
6024
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6025 6026 6027 6028
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

6029
#define GEN_VR_LDX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6030
static void glue(gen_, name)(DisasContext *ctx)                                       \
6031
{                                                                             \
6032
    TCGv EA;                                                                  \
6033
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6034
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6035 6036
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6037
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6038
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6039
    gen_addr_reg_index(ctx, EA);                                              \
6040
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6041 6042
    if (ctx->le_mode) {                                                       \
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6043
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6044
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6045
    } else {                                                                  \
A
aurel32 已提交
6046
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6047
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6048
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6049 6050
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6051 6052 6053
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6054
static void gen_st##name(DisasContext *ctx)                                   \
6055
{                                                                             \
6056
    TCGv EA;                                                                  \
6057
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6058
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6059 6060
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6061
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6062
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6063
    gen_addr_reg_index(ctx, EA);                                              \
6064
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6065 6066
    if (ctx->le_mode) {                                                       \
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6067
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6068
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6069
    } else {                                                                  \
A
aurel32 已提交
6070
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6071
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6072
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6073 6074
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6075 6076
}

A
aurel32 已提交
6077
#define GEN_VR_LVE(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6078
static void gen_lve##name(DisasContext *ctx)                            \
A
aurel32 已提交
6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095
    {                                                                   \
        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 已提交
6096
static void gen_stve##name(DisasContext *ctx)                           \
A
aurel32 已提交
6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112
    {                                                                   \
        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);                                          \
    }

6113
GEN_VR_LDX(lvx, 0x07, 0x03);
6114
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6115
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6116

A
aurel32 已提交
6117 6118 6119 6120
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6121
GEN_VR_STX(svx, 0x07, 0x07);
6122
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6123
GEN_VR_STX(svxl, 0x07, 0x0F);
6124

A
aurel32 已提交
6125 6126 6127 6128
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

B
Blue Swirl 已提交
6129
static void gen_lvsl(DisasContext *ctx)
A
aurel32 已提交
6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144
{
    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 已提交
6145
static void gen_lvsr(DisasContext *ctx)
A
aurel32 已提交
6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160
{
    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 已提交
6161
static void gen_mfvscr(DisasContext *ctx)
6162 6163 6164 6165 6166 6167 6168 6169 6170 6171
{
    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);
6172
    tcg_temp_free_i32(t);
6173 6174
}

B
Blue Swirl 已提交
6175
static void gen_mtvscr(DisasContext *ctx)
6176
{
A
aurel32 已提交
6177
    TCGv_ptr p;
6178 6179 6180 6181
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6182 6183 6184
    p = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_mtvscr(p);
    tcg_temp_free_ptr(p);
6185 6186
}

6187 6188
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
B
Blue Swirl 已提交
6189
static void glue(gen_, name)(DisasContext *ctx)                                 \
6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204
{                                                                       \
    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);

6205
#define GEN_VXFORM(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6206
static void glue(gen_, name)(DisasContext *ctx)                                 \
6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221
{                                                                       \
    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 已提交
6222 6223 6224 6225 6226 6227
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);
6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239
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 已提交
6240 6241 6242 6243 6244 6245
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 已提交
6246 6247 6248 6249 6250 6251
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 已提交
6252 6253 6254 6255 6256 6257 6258 6259
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 已提交
6260 6261 6262
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6263 6264 6265 6266 6267 6268
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 已提交
6269 6270
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6271 6272
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284
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 已提交
6285 6286 6287
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6288 6289
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6290 6291 6292 6293 6294 6295 6296 6297
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 已提交
6298
GEN_VXFORM(vpkpx, 7, 12);
6299 6300 6301 6302 6303
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);
6304 6305
GEN_VXFORM(vaddfp, 5, 0);
GEN_VXFORM(vsubfp, 5, 1);
6306 6307
GEN_VXFORM(vmaxfp, 5, 16);
GEN_VXFORM(vminfp, 5, 17);
A
aurel32 已提交
6308

6309
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
B
Blue Swirl 已提交
6310
static void glue(gen_, name)(DisasContext *ctx)                         \
6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329
    {                                                                   \
        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)))

6330 6331 6332 6333 6334 6335 6336 6337 6338
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)
6339 6340 6341 6342
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6343

A
aurel32 已提交
6344
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6345
static void glue(gen_, name)(DisasContext *ctx)                         \
A
aurel32 已提交
6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363
    {                                                                   \
        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);

6364
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
B
Blue Swirl 已提交
6365
static void glue(gen_, name)(DisasContext *ctx)                                 \
6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378
    {                                                                   \
        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 已提交
6379 6380 6381 6382
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 已提交
6383 6384
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
A
aurel32 已提交
6385
GEN_VXFORM_NOA(vrefp, 5, 4);
A
aurel32 已提交
6386
GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
6387
GEN_VXFORM_NOA(vlogefp, 5, 7);
A
aurel32 已提交
6388 6389 6390 6391
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 已提交
6392

6393
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6394
static void glue(gen_, name)(DisasContext *ctx)                                 \
6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408
    {                                                                   \
        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);                                          \
    }

6409
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6410
static void glue(gen_, name)(DisasContext *ctx)                                 \
6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426
    {                                                                   \
        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 已提交
6427 6428 6429
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
A
aurel32 已提交
6430 6431
GEN_VXFORM_UIMM(vcfux, 5, 12);
GEN_VXFORM_UIMM(vcfsx, 5, 13);
6432 6433
GEN_VXFORM_UIMM(vctuxs, 5, 14);
GEN_VXFORM_UIMM(vctsxs, 5, 15);
A
aurel32 已提交
6434

B
Blue Swirl 已提交
6435
static void gen_vsldoi(DisasContext *ctx)
A
aurel32 已提交
6436 6437
{
    TCGv_ptr ra, rb, rd;
6438
    TCGv_i32 sh;
A
aurel32 已提交
6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450
    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);
6451
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6452 6453
}

6454
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
B
Blue Swirl 已提交
6455
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                      \
6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476
    {                                                                   \
        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 已提交
6477 6478
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

B
Blue Swirl 已提交
6479
static void gen_vmladduhm(DisasContext *ctx)
A
aurel32 已提交
6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496
{
    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 已提交
6497
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6498
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6499
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6500
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6501
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6502

6503 6504
/***                           SPE extension                               ***/
/* Register moves */
6505

B
Blue Swirl 已提交
6506 6507
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
A
aurel32 已提交
6508 6509 6510
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
6511
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6512
#endif
A
aurel32 已提交
6513
}
6514

B
Blue Swirl 已提交
6515 6516
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
6517 6518 6519
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6520
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6521 6522 6523
    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 已提交
6524
    tcg_temp_free_i64(tmp);
6525
#endif
A
aurel32 已提交
6526
}
6527

6528
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
B
Blue Swirl 已提交
6529
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
6530 6531 6532 6533 6534 6535 6536 6537
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
6538
static inline void gen_speundef(DisasContext *ctx)
6539
{
A
aurel32 已提交
6540
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6541 6542
}

6543 6544 6545
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6546
static inline void gen_##name(DisasContext *ctx)                              \
6547 6548
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6549
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6550 6551
        return;                                                               \
    }                                                                         \
6552 6553 6554 6555 6556
    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 已提交
6557
static inline void gen_##name(DisasContext *ctx)                              \
6558 6559
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6560
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6561 6562 6563 6564 6565 6566
        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)]);                                        \
6567
}
6568 6569 6570 6571 6572 6573 6574 6575 6576 6577
#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);
6578

6579 6580 6581
/* SPE logic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6582
static inline void gen_##name(DisasContext *ctx)                              \
6583 6584
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6585
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6586 6587
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6588 6589 6590
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6591 6592 6593 6594
    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 已提交
6595
    tcg_temp_free_i64(t2);                                                    \
6596 6597
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6598 6599
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6600
}
6601 6602
#else
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6603
static inline void gen_##name(DisasContext *ctx)                              \
6604 6605
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6606
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6607 6608
        return;                                                               \
    }                                                                         \
6609 6610 6611 6612
    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));                                                 \
6613
}
6614 6615 6616 6617 6618
#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);
6619

6620 6621 6622
/* SPE arithmetic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
6623
static inline void gen_##name(DisasContext *ctx)                              \
6624 6625
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6626
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6627 6628
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6629 6630 6631
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6632 6633 6634 6635
    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 已提交
6636
    tcg_temp_free_i64(t2);                                                    \
6637 6638
    tcg_op(t1, t1);                                                           \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6639 6640
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6641
}
6642
#else
P
pbrook 已提交
6643
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
6644
static inline void gen_##name(DisasContext *ctx)                              \
6645 6646
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6647
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6648 6649 6650 6651 6652 6653
        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
6654

B
Blue Swirl 已提交
6655
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
6656 6657 6658
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
6659

6660 6661 6662 6663
    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 已提交
6664
    tcg_gen_mov_i32(ret, arg1);
6665 6666 6667 6668 6669 6670
    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 已提交
6671
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
6672
{
6673 6674 6675 6676
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
6677 6678
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6679

6680 6681
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6682
static inline void gen_##name(DisasContext *ctx)                              \
6683 6684
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6685
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6686 6687
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6688 6689 6690
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
6691
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
6692 6693 6694 6695 6696 6697 6698
    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 已提交
6699
    tcg_temp_free_i64(t3);                                                    \
6700
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
6701
    tcg_temp_free_i32(t2);                                                    \
6702
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6703 6704
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6705
}
6706 6707
#else
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6708
static inline void gen_##name(DisasContext *ctx)                              \
6709 6710
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6711
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6712 6713
        return;                                                               \
    }                                                                         \
6714 6715 6716 6717
    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)]);                                        \
6718
}
6719
#endif
6720

B
Blue Swirl 已提交
6721
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6722
{
P
pbrook 已提交
6723
    TCGv_i32 t0;
6724
    int l1, l2;
6725

6726 6727
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6728
    t0 = tcg_temp_local_new_i32();
6729 6730 6731 6732 6733 6734 6735
    /* 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);
6736
    gen_set_label(l2);
P
pbrook 已提交
6737
    tcg_temp_free_i32(t0);
6738 6739
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
6740
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6741
{
P
pbrook 已提交
6742
    TCGv_i32 t0;
6743 6744 6745 6746
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6747
    t0 = tcg_temp_local_new_i32();
6748 6749 6750 6751 6752 6753 6754
    /* 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);
6755
    gen_set_label(l2);
P
pbrook 已提交
6756
    tcg_temp_free_i32(t0);
6757 6758
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
6759
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6760
{
P
pbrook 已提交
6761
    TCGv_i32 t0;
6762 6763 6764 6765
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6766
    t0 = tcg_temp_local_new_i32();
6767 6768 6769 6770 6771 6772 6773
    /* 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);
6774
    gen_set_label(l2);
P
pbrook 已提交
6775
    tcg_temp_free_i32(t0);
6776 6777
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
B
Blue Swirl 已提交
6778
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6779
{
P
pbrook 已提交
6780
    TCGv_i32 t0 = tcg_temp_new_i32();
6781 6782
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
6783
    tcg_temp_free_i32(t0);
6784 6785
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
B
Blue Swirl 已提交
6786
static inline void gen_evmergehi(DisasContext *ctx)
6787 6788
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
6789
        gen_exception(ctx, POWERPC_EXCP_APU);
6790 6791 6792
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6793 6794
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805
    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 已提交
6806
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6807
{
6808 6809 6810
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
6811

6812 6813 6814
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
6815
static inline void gen_##name(DisasContext *ctx)                              \
6816 6817
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6818
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6819 6820
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6821 6822 6823
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6824 6825 6826 6827
    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 已提交
6828
    tcg_temp_free_i64(t2);                                                    \
6829 6830
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6831 6832
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6833 6834 6835
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
6836
static inline void gen_##name(DisasContext *ctx)                              \
6837 6838
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6839
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853
        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 已提交
6854
static inline void gen_##name(DisasContext *ctx)                              \
6855 6856
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6857
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6858 6859 6860 6861 6862 6863
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
6864 6865 6866
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6867 6868 6869
    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 已提交
6870
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
6871 6872 6873 6874 6875 6876 6877 6878 6879
    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 已提交
6880
    tcg_temp_free_i64(t2);                                                    \
6881 6882 6883 6884 6885 6886 6887 6888
    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 已提交
6889 6890
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6891 6892 6893
}
#else
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
B
Blue Swirl 已提交
6894
static inline void gen_##name(DisasContext *ctx)                              \
6895 6896
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6897
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930
        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 已提交
6931
static inline void gen_brinc(DisasContext *ctx)
6932 6933
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
6934 6935
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6936
}
B
Blue Swirl 已提交
6937
static inline void gen_evmergelo(DisasContext *ctx)
6938 6939
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
6940
        gen_exception(ctx, POWERPC_EXCP_APU);
6941 6942 6943
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6944 6945
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6946 6947 6948 6949 6950 6951 6952
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
    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)]);
6953
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6954 6955
#endif
}
B
Blue Swirl 已提交
6956
static inline void gen_evmergehilo(DisasContext *ctx)
6957 6958
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
6959
        gen_exception(ctx, POWERPC_EXCP_APU);
6960 6961 6962
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6963 6964
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6965 6966 6967 6968 6969 6970 6971 6972 6973 6974
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
    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 已提交
6975
static inline void gen_evmergelohi(DisasContext *ctx)
6976 6977
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
6978
        gen_exception(ctx, POWERPC_EXCP_APU);
6979 6980 6981
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6982 6983
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6984 6985 6986 6987 6988 6989
    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
6990 6991 6992 6993 6994 6995 6996 6997 6998 6999
    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)]);
    }
7000 7001
#endif
}
B
Blue Swirl 已提交
7002
static inline void gen_evsplati(DisasContext *ctx)
7003
{
7004
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
7005

7006
#if defined(TARGET_PPC64)
7007
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7008 7009 7010 7011 7012
#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 已提交
7013
static inline void gen_evsplatfi(DisasContext *ctx)
7014
{
7015
    uint64_t imm = rA(ctx->opcode) << 27;
7016

7017
#if defined(TARGET_PPC64)
7018
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7019 7020 7021 7022
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7023 7024
}

B
Blue Swirl 已提交
7025
static inline void gen_evsel(DisasContext *ctx)
7026 7027 7028 7029 7030
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7031
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7032
#if defined(TARGET_PPC64)
P
pbrook 已提交
7033 7034
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065
#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)
    tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
#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)
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7066
    tcg_temp_free_i32(t0);
7067 7068 7069 7070 7071 7072
#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 已提交
7073 7074

static void gen_evsel0(DisasContext *ctx)
7075 7076 7077
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7078 7079

static void gen_evsel1(DisasContext *ctx)
7080 7081 7082
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7083 7084

static void gen_evsel2(DisasContext *ctx)
7085 7086 7087
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7088 7089

static void gen_evsel3(DisasContext *ctx)
7090 7091 7092
{
    gen_evsel(ctx);
}
7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119

GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE); ////
GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE); ////
GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE); ////
GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE); //
GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE); //
GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE); ////

7120
/* SPE load and stores */
B
Blue Swirl 已提交
7121
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7122 7123 7124
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7125
    if (rA(ctx->opcode) == 0) {
7126
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7127
    } else {
7128
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
A
aurel32 已提交
7129 7130 7131 7132 7133 7134
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
7135
}
7136

B
Blue Swirl 已提交
7137
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7138 7139
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7140
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7141 7142
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7143
    gen_qemu_ld64(ctx, t0, addr);
7144 7145 7146 7147 7148
    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
7149
}
7150

B
Blue Swirl 已提交
7151
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7152
{
7153
#if defined(TARGET_PPC64)
7154
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7155
    gen_qemu_ld32u(ctx, t0, addr);
7156
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7157 7158
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7159 7160 7161
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7162 7163 7164
    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);
7165
#endif
7166
}
7167

B
Blue Swirl 已提交
7168
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7169 7170 7171
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7172
    gen_qemu_ld16u(ctx, t0, addr);
7173
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7174 7175
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7176 7177
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7178 7179
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7180 7181
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7182 7183
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7184
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7185
#else
A
aurel32 已提交
7186
    gen_qemu_ld16u(ctx, t0, addr);
7187
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7188 7189
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7190
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7191 7192
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7193
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7194 7195
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7196
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7197
#endif
7198
    tcg_temp_free(t0);
7199 7200
}

B
Blue Swirl 已提交
7201
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7202 7203
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7204
    gen_qemu_ld16u(ctx, t0, addr);
7205 7206 7207 7208 7209 7210 7211 7212 7213 7214
#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);
7215 7216
}

B
Blue Swirl 已提交
7217
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7218 7219
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7220
    gen_qemu_ld16u(ctx, t0, addr);
7221 7222 7223 7224 7225 7226 7227 7228
#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);
7229 7230
}

B
Blue Swirl 已提交
7231
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7232 7233
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7234
    gen_qemu_ld16s(ctx, t0, addr);
7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245
#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 已提交
7246
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7247 7248 7249
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7250
    gen_qemu_ld16u(ctx, t0, addr);
7251
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7252 7253
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7254 7255 7256
    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 已提交
7257
    gen_qemu_ld16u(ctx, t0, addr);
7258
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7259 7260
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7261 7262 7263 7264 7265
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7266
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7267 7268 7269
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7270 7271 7272
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7273 7274 7275 7276
    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 已提交
7277 7278 7279
    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);
7280 7281 7282
#endif
}

B
Blue Swirl 已提交
7283
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7284 7285 7286
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7287
    gen_qemu_ld16s(ctx, t0, addr);
7288
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7289 7290
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7291 7292 7293 7294
    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 已提交
7295 7296 7297
    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);
7298 7299 7300
#endif
}

B
Blue Swirl 已提交
7301
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7302 7303
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7304
    gen_qemu_ld32u(ctx, t0, addr);
7305
#if defined(TARGET_PPC64)
7306 7307 7308 7309 7310 7311 7312 7313 7314
    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 已提交
7315
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7316 7317 7318
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7319
    gen_qemu_ld16u(ctx, t0, addr);
7320 7321 7322
    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 已提交
7323 7324
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7325 7326 7327 7328
    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 已提交
7329
    gen_qemu_ld16u(ctx, t0, addr);
7330 7331
    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 已提交
7332 7333
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7334 7335
    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);
7336
#endif
7337 7338 7339
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7340
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7341 7342
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7343
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7344
#else
7345 7346
    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 已提交
7347
    gen_qemu_st64(ctx, t0, addr);
7348 7349 7350 7351
    tcg_temp_free_i64(t0);
#endif
}

B
Blue Swirl 已提交
7352
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7353
{
7354
#if defined(TARGET_PPC64)
7355 7356
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7357
    gen_qemu_st32(ctx, t0, addr);
7358 7359
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7360
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7361
#endif
A
aurel32 已提交
7362 7363
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7364 7365
}

B
Blue Swirl 已提交
7366
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7367 7368 7369 7370 7371 7372 7373
{
    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 已提交
7374 7375
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7376 7377
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7378
    gen_qemu_st16(ctx, t0, addr);
7379
#else
A
aurel32 已提交
7380
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7381
#endif
A
aurel32 已提交
7382
    gen_addr_add(ctx, addr, addr, 2);
7383
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7384
    gen_qemu_st16(ctx, t0, addr);
7385
    tcg_temp_free(t0);
A
aurel32 已提交
7386 7387
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7388 7389
}

B
Blue Swirl 已提交
7390
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7391 7392 7393 7394 7395 7396 7397
{
    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 已提交
7398 7399
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7400
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7401
    gen_qemu_st16(ctx, t0, addr);
7402 7403 7404
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7405
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7406 7407 7408 7409
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7410
    gen_qemu_st16(ctx, t0, addr);
7411 7412
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7413
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7414
#endif
A
aurel32 已提交
7415 7416
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7417 7418
}

B
Blue Swirl 已提交
7419
static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7420 7421 7422 7423
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7424
    gen_qemu_st32(ctx, t0, addr);
7425 7426
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7427
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7428 7429 7430
#endif
}

B
Blue Swirl 已提交
7431
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7432
{
A
aurel32 已提交
7433
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7434 7435 7436
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
B
Blue Swirl 已提交
7437
static void glue(gen_, name)(DisasContext *ctx)                                       \
7438 7439 7440
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7441
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7442 7443
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7444
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7445 7446
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
7447
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7448
    } else {                                                                  \
A
aurel32 已提交
7449
        gen_addr_reg_index(ctx, t0);                                          \
7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473
    }                                                                         \
    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);
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 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 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551

/* Multiply and add - TODO */
#if 0
GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0x00000000, PPC_SPE);

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

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

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

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

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

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

/***                      SPE floating-point extension                     ***/
A
aurel32 已提交
7552 7553
#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
7554
static inline void gen_##name(DisasContext *ctx)                              \
7555
{                                                                             \
A
aurel32 已提交
7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567
    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);                                                        \
7568
}
A
aurel32 已提交
7569
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
7570
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584
{                                                                             \
    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 已提交
7585
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7586 7587 7588 7589 7590 7591 7592
{                                                                             \
    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 已提交
7593
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7594 7595 7596 7597
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
7598
static inline void gen_##name(DisasContext *ctx)                              \
7599
{                                                                             \
A
aurel32 已提交
7600 7601
    TCGv_i32 t0, t1;                                                          \
    TCGv_i64 t2;                                                              \
7602
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7603
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7604 7605
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618
    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);                                                        \
7619
}
A
aurel32 已提交
7620
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
7621
static inline void gen_##name(DisasContext *ctx)                              \
7622 7623
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7624
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7625 7626
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7627 7628
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],     \
                      cpu_gpr[rB(ctx->opcode)]);                              \
7629
}
A
aurel32 已提交
7630
#define GEN_SPEFPUOP_COMP_32(name)                                            \
B
Blue Swirl 已提交
7631
static inline void gen_##name(DisasContext *ctx)                              \
7632
{                                                                             \
A
aurel32 已提交
7633
    TCGv_i32 t0, t1;                                                          \
7634
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7635
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7636 7637
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7638 7639 7640 7641 7642 7643 7644 7645 7646
    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 已提交
7647
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7648 7649
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7650
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7651 7652 7653 7654 7655 7656 7657
        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 已提交
7658
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7659 7660
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7661
}
A
aurel32 已提交
7662
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
7663
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7664 7665 7666 7667 7668 7669 7670
{                                                                             \
    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 已提交
7671
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7672 7673 7674 7675 7676 7677 7678
{                                                                             \
    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 已提交
7679
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7680 7681 7682 7683 7684 7685 7686 7687
{                                                                             \
    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 已提交
7688
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7689 7690
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7691
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7692 7693 7694 7695 7696 7697
        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 已提交
7698
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7699 7700 7701
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7702
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714
        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 已提交
7715
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7716 7717
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7718
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7719 7720 7721 7722 7723 7724
        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 已提交
7725
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7726 7727 7728
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7729
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740
        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
7741

7742 7743
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
7744 7745 7746 7747
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 已提交
7748
static inline void gen_evfsabs(DisasContext *ctx)
A
aurel32 已提交
7749 7750
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7751
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7752 7753 7754 7755 7756 7757 7758 7759 7760
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
#else
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
#endif
}
B
Blue Swirl 已提交
7761
static inline void gen_evfsnabs(DisasContext *ctx)
A
aurel32 已提交
7762 7763
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7764
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7765 7766 7767 7768 7769 7770 7771 7772 7773
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
#else
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}
B
Blue Swirl 已提交
7774
static inline void gen_evfsneg(DisasContext *ctx)
A
aurel32 已提交
7775 7776
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7777
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7778 7779 7780 7781 7782 7783 7784 7785 7786 7787
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
#else
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}

7788
/* Conversion */
A
aurel32 已提交
7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799
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);

7800
/* Comparison */
A
aurel32 已提交
7801 7802 7803 7804 7805 7806
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);
7807 7808

/* Opcodes definitions */
7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822
GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7823 7824 7825

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
7826 7827 7828 7829
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 已提交
7830
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
7831 7832
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7833
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7834 7835 7836 7837
        return;
    }
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
}
B
Blue Swirl 已提交
7838
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
7839 7840
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7841
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7842 7843 7844 7845
        return;
    }
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
}
B
Blue Swirl 已提交
7846
static inline void gen_efsneg(DisasContext *ctx)
A
aurel32 已提交
7847 7848
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7849
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7850 7851 7852 7853 7854
        return;
    }
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
}

7855
/* Conversion */
A
aurel32 已提交
7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867
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);

7868
/* Comparison */
A
aurel32 已提交
7869 7870 7871 7872 7873 7874
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);
7875 7876

/* Opcodes definitions */
7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7891 7892 7893

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
7894 7895 7896 7897
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 已提交
7898
static inline void gen_efdabs(DisasContext *ctx)
A
aurel32 已提交
7899 7900
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7901
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7902 7903 7904 7905 7906 7907 7908 7909
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
#else
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
#endif
}
B
Blue Swirl 已提交
7910
static inline void gen_efdnabs(DisasContext *ctx)
A
aurel32 已提交
7911 7912
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7913
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7914 7915 7916 7917 7918 7919 7920 7921
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
#else
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}
B
Blue Swirl 已提交
7922
static inline void gen_efdneg(DisasContext *ctx)
A
aurel32 已提交
7923 7924
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7925
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7926 7927 7928 7929 7930 7931 7932 7933 7934
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
#else
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}

7935
/* Conversion */
A
aurel32 已提交
7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950
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);
7951 7952

/* Comparison */
A
aurel32 已提交
7953 7954 7955 7956 7957 7958
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);
7959 7960

/* Opcodes definitions */
7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7977

A
Anthony Liguori 已提交
7978
static opcode_t opcodes[] = {
7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201
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),
#if defined(TARGET_PPC64)
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),
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES),
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B),
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),
GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B),
#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),
GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE),
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),
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8202
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 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 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 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 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 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
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
GEN_HANDLER(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, PPC_BOOKE),
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE),
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),
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
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)
GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE),
GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE),
GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE),
GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE),
GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE),
GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE),
GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE),

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

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

GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE),

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

8828
#include "translate_init.c"
8829
#include "helper_regs.h"
B
bellard 已提交
8830

8831
/*****************************************************************************/
8832
/* Misc PowerPC helpers */
8833 8834 8835
void cpu_dump_state (CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
B
bellard 已提交
8836
{
8837 8838 8839
#define RGPL  4
#define RFPL  4

B
bellard 已提交
8840 8841
    int i;

8842 8843 8844 8845 8846 8847
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
                TARGET_FMT_lx " XER %08x\n", env->nip, env->lr, env->ctr,
                env->xer);
    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);
8848
#if !defined(NO_TIMER_DUMP)
J
j_mayer 已提交
8849
    cpu_fprintf(f, "TB %08x %08x "
8850 8851 8852 8853
#if !defined(CONFIG_USER_ONLY)
                "DECR %08x"
#endif
                "\n",
J
j_mayer 已提交
8854
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
8855 8856 8857 8858
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
8859
#endif
8860
    for (i = 0; i < 32; i++) {
8861 8862
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
8863
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
8864
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
8865
            cpu_fprintf(f, "\n");
8866
    }
8867
    cpu_fprintf(f, "CR ");
8868
    for (i = 0; i < 8; i++)
B
bellard 已提交
8869 8870
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
8871 8872 8873 8874 8875 8876 8877 8878
    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 已提交
8879
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
8880
    }
8881 8882
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
8883 8884 8885
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
8886
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
8887
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
8888
            cpu_fprintf(f, "\n");
B
bellard 已提交
8889
    }
8890
    cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
8891
#if !defined(CONFIG_USER_ONLY)
8892 8893 8894
    cpu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx " SDR1 "
                TARGET_FMT_lx "\n", env->spr[SPR_SRR0], env->spr[SPR_SRR1],
                env->sdr1);
8895
#endif
B
bellard 已提交
8896

8897 8898
#undef RGPL
#undef RFPL
B
bellard 已提交
8899 8900
}

8901 8902 8903 8904 8905
void cpu_dump_statistics (CPUState *env, FILE*f,
                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
A
Anthony Liguori 已提交
8906
    opc_handler_t **t1, **t2, **t3, *handler;
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
    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: "
                                    "%016llx %lld\n",
                                    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: "
                                "%016llx %lld\n",
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016llx %lld\n",
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

8948
/*****************************************************************************/
B
Blue Swirl 已提交
8949 8950 8951
static inline void gen_intermediate_code_internal(CPUState *env,
                                                  TranslationBlock *tb,
                                                  int search_pc)
B
bellard 已提交
8952
{
8953
    DisasContext ctx, *ctxp = &ctx;
A
Anthony Liguori 已提交
8954
    opc_handler_t **table, *handler;
B
bellard 已提交
8955
    target_ulong pc_start;
B
bellard 已提交
8956
    uint16_t *gen_opc_end;
8957
    CPUBreakpoint *bp;
B
bellard 已提交
8958
    int j, lj = -1;
P
pbrook 已提交
8959 8960
    int num_insns;
    int max_insns;
B
bellard 已提交
8961 8962 8963

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
8964
    ctx.nip = pc_start;
B
bellard 已提交
8965
    ctx.tb = tb;
8966
    ctx.exception = POWERPC_EXCP_NONE;
8967
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
8968 8969 8970
    ctx.mem_idx = env->mmu_idx;
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
8971 8972
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
8973
#endif
B
bellard 已提交
8974
    ctx.fpu_enabled = msr_fp;
8975
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
8976 8977 8978
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
8979 8980 8981 8982
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
8983
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8984
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
8985
    else
8986
        ctx.singlestep_enabled = 0;
8987
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8988 8989 8990
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
8991
#if defined (DO_SINGLE_STEP) && 0
8992 8993 8994
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
8995 8996 8997 8998 8999 9000
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
9001
    /* Set env in case of segfault during code fetch */
9002
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
B
Blue Swirl 已提交
9003 9004
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9005
                if (bp->pc == ctx.nip) {
A
aurel32 已提交
9006
                    gen_debug_exception(ctxp);
9007 9008 9009 9010
                    break;
                }
            }
        }
9011
        if (unlikely(search_pc)) {
B
bellard 已提交
9012 9013 9014 9015 9016 9017
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
            }
9018 9019 9020
            gen_opc_pc[lj] = ctx.nip;
            gen_opc_instr_start[lj] = 1;
            gen_opc_icount[lj] = num_insns;
B
bellard 已提交
9021
        }
9022
        LOG_DISAS("----------------\n");
9023
        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
9024
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
P
pbrook 已提交
9025 9026
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
A
aurel32 已提交
9027
        if (unlikely(ctx.le_mode)) {
9028 9029 9030
            ctx.opcode = bswap32(ldl_code(ctx.nip));
        } else {
            ctx.opcode = ldl_code(ctx.nip);
9031
        }
9032
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9033
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
9034
                    opc3(ctx.opcode), little_endian ? "little" : "big");
9035 9036
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
            tcg_gen_debug_insn_start(ctx.nip);
B
bellard 已提交
9037
        ctx.nip += 4;
9038
        table = env->opcodes;
P
pbrook 已提交
9039
        num_insns++;
B
bellard 已提交
9040 9041 9042 9043 9044 9045 9046 9047 9048 9049
        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 ? */
9050
        if (unlikely(handler->handler == &gen_invalid)) {
9051 9052
            if (qemu_log_enabled()) {
                qemu_log("invalid/unsupported opcode: "
9053 9054 9055
                         "%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 已提交
9056
            }
9057 9058
        } else {
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
9059 9060
                if (qemu_log_enabled()) {
                    qemu_log("invalid bits: %08x for opcode: "
9061 9062 9063 9064
                             "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
                             ctx.opcode & handler->inval, opc1(ctx.opcode),
                             opc2(ctx.opcode), opc3(ctx.opcode),
                             ctx.opcode, ctx.nip - 4);
9065
                }
A
aurel32 已提交
9066
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
B
bellard 已提交
9067
                break;
B
bellard 已提交
9068 9069
            }
        }
B
bellard 已提交
9070
        (*(handler->handler))(&ctx);
9071 9072 9073
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
9074
        /* Check trace mode exceptions */
9075 9076 9077 9078 9079
        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 已提交
9080
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
9081
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
9082
                            (env->singlestep_enabled) ||
9083
                            singlestep ||
P
pbrook 已提交
9084
                            num_insns >= max_insns)) {
9085 9086 9087
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
9088
            break;
9089
        }
9090
    }
P
pbrook 已提交
9091 9092
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
9093
    if (ctx.exception == POWERPC_EXCP_NONE) {
9094
        gen_goto_tb(&ctx, 0, ctx.nip);
9095
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
9096
        if (unlikely(env->singlestep_enabled)) {
A
aurel32 已提交
9097
            gen_debug_exception(ctxp);
9098
        }
9099
        /* Generate the return instruction */
B
bellard 已提交
9100
        tcg_gen_exit_tb(0);
9101
    }
P
pbrook 已提交
9102
    gen_icount_end(tb, num_insns);
B
bellard 已提交
9103
    *gen_opc_ptr = INDEX_op_end;
9104
    if (unlikely(search_pc)) {
9105 9106 9107 9108 9109
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
B
bellard 已提交
9110
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
9111
        tb->icount = num_insns;
9112
    }
9113
#if defined(DEBUG_DISAS)
9114 9115
    qemu_log_mask(CPU_LOG_TB_CPU, "---------------- excp: %04x\n", ctx.exception);
    log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
9116
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9117
        int flags;
9118
        flags = env->bfd_mach;
A
aurel32 已提交
9119
        flags |= ctx.le_mode << 16;
9120 9121 9122
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
        log_target_disas(pc_start, ctx.nip - pc_start, flags);
        qemu_log("\n");
9123
    }
B
bellard 已提交
9124 9125 9126
#endif
}

9127
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
9128
{
9129
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
9130 9131
}

9132
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
9133
{
9134
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
9135
}
A
aurel32 已提交
9136 9137 9138 9139 9140 9141

void gen_pc_load(CPUState *env, TranslationBlock *tb,
                unsigned long searched_pc, int pc_pos, void *puc)
{
    env->nip = gen_opc_pc[pc_pos];
}