translate.c 339.5 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
    int l1;
3402
    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
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4230 4231
#endif /* defined(TARGET_PPC64) */

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

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

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

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

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

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

B
bellard 已提交
4332 4333
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4334

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/* sraq - sraq. */
B
Blue Swirl 已提交
4827
static void gen_sraq(DisasContext *ctx)
4828
{
4829 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
    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);
4855
    if (unlikely(Rc(ctx->opcode) != 0))
4856
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4857 4858 4859
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

5062
/* 74xx TLB management */
B
Blue Swirl 已提交
5063

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

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

5092
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5093

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

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

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

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

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

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

/* svc is not implemented for now */

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

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

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

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

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

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

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

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

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

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

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

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

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

P
pbrook 已提交
5344 5345
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5346

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

5782
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5783

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

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

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

5859
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
5860

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

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

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

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

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

J
j_mayer 已提交
5985
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
5986

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

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

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

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

6017 6018 6019
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537

static inline void gen_evmra(DisasContext *ctx)
{

    if (unlikely(!ctx->spe_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_APU);
        return;
    }

#if defined(TARGET_PPC64)
    /* rD := rA */
    tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);

    /* spe_acc := rA */
    tcg_gen_st_i64(cpu_gpr[rA(ctx->opcode)],
                   cpu_env,
                   offsetof(CPUState, spe_acc));
#else
    TCGv_i64 tmp = tcg_temp_new_i64();

    /* tmp := rA_lo + rA_hi << 32 */
    tcg_gen_concat_i32_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);

    /* spe_acc := tmp */
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
    tcg_temp_free_i64(tmp);

    /* rD := rA */
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
}

B
Blue Swirl 已提交
6538 6539
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
A
aurel32 已提交
6540 6541 6542
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
6543
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6544
#endif
A
aurel32 已提交
6545
}
6546

B
Blue Swirl 已提交
6547 6548
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
6549 6550 6551
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6552
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6553 6554 6555
    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 已提交
6556
    tcg_temp_free_i64(tmp);
6557
#endif
A
aurel32 已提交
6558
}
6559

6560
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
B
Blue Swirl 已提交
6561
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
6562 6563 6564 6565 6566 6567 6568 6569
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
6570
static inline void gen_speundef(DisasContext *ctx)
6571
{
A
aurel32 已提交
6572
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6573 6574
}

6575 6576 6577
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6578
static inline void gen_##name(DisasContext *ctx)                              \
6579 6580
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6581
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6582 6583
        return;                                                               \
    }                                                                         \
6584 6585 6586 6587 6588
    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 已提交
6589
static inline void gen_##name(DisasContext *ctx)                              \
6590 6591
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6592
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6593 6594 6595 6596 6597 6598
        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)]);                                        \
6599
}
6600 6601 6602 6603 6604 6605 6606 6607 6608 6609
#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);
6610

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

6652 6653 6654
/* SPE arithmetic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
6655
static inline void gen_##name(DisasContext *ctx)                              \
6656 6657
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6658
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6659 6660
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6661 6662 6663
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6664 6665 6666 6667
    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 已提交
6668
    tcg_temp_free_i64(t2);                                                    \
6669 6670
    tcg_op(t1, t1);                                                           \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6671 6672
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6673
}
6674
#else
P
pbrook 已提交
6675
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
6676
static inline void gen_##name(DisasContext *ctx)                              \
6677 6678
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6679
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6680 6681 6682 6683 6684 6685
        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
6686

B
Blue Swirl 已提交
6687
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
6688 6689 6690
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
6691

6692 6693 6694 6695
    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 已提交
6696
    tcg_gen_mov_i32(ret, arg1);
6697 6698 6699 6700 6701 6702
    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 已提交
6703
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
6704
{
6705 6706 6707 6708
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
6709 6710
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6711

6712 6713
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6714
static inline void gen_##name(DisasContext *ctx)                              \
6715 6716
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6717
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6718 6719
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6720 6721 6722
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
6723
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
6724 6725 6726 6727 6728 6729 6730
    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 已提交
6731
    tcg_temp_free_i64(t3);                                                    \
6732
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
6733
    tcg_temp_free_i32(t2);                                                    \
6734
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6735 6736
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6737
}
6738 6739
#else
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6740
static inline void gen_##name(DisasContext *ctx)                              \
6741 6742
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6743
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6744 6745
        return;                                                               \
    }                                                                         \
6746 6747 6748 6749
    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)]);                                        \
6750
}
6751
#endif
6752

B
Blue Swirl 已提交
6753
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6754
{
P
pbrook 已提交
6755
    TCGv_i32 t0;
6756
    int l1, l2;
6757

6758 6759
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6760
    t0 = tcg_temp_local_new_i32();
6761 6762 6763 6764 6765 6766 6767
    /* 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);
6768
    gen_set_label(l2);
P
pbrook 已提交
6769
    tcg_temp_free_i32(t0);
6770 6771
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
6772
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6773
{
P
pbrook 已提交
6774
    TCGv_i32 t0;
6775 6776 6777 6778
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6779
    t0 = tcg_temp_local_new_i32();
6780 6781 6782 6783 6784 6785 6786
    /* 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);
6787
    gen_set_label(l2);
P
pbrook 已提交
6788
    tcg_temp_free_i32(t0);
6789 6790
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
6791
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6792
{
P
pbrook 已提交
6793
    TCGv_i32 t0;
6794 6795 6796 6797
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6798
    t0 = tcg_temp_local_new_i32();
6799 6800 6801 6802 6803 6804 6805
    /* 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);
6806
    gen_set_label(l2);
P
pbrook 已提交
6807
    tcg_temp_free_i32(t0);
6808 6809
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
B
Blue Swirl 已提交
6810
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6811
{
P
pbrook 已提交
6812
    TCGv_i32 t0 = tcg_temp_new_i32();
6813 6814
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
6815
    tcg_temp_free_i32(t0);
6816 6817
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
B
Blue Swirl 已提交
6818
static inline void gen_evmergehi(DisasContext *ctx)
6819 6820
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
6821
        gen_exception(ctx, POWERPC_EXCP_APU);
6822 6823 6824
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6825 6826
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837
    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 已提交
6838
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6839
{
6840 6841 6842
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
6843

6844 6845 6846
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
6847
static inline void gen_##name(DisasContext *ctx)                              \
6848 6849
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6850
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6851 6852
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6853 6854 6855
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6856 6857 6858 6859
    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 已提交
6860
    tcg_temp_free_i64(t2);                                                    \
6861 6862
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6863 6864
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6865 6866 6867
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
6868
static inline void gen_##name(DisasContext *ctx)                              \
6869 6870
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6871
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885
        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 已提交
6886
static inline void gen_##name(DisasContext *ctx)                              \
6887 6888
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6889
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6890 6891 6892 6893 6894 6895
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
6896 6897 6898
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6899 6900 6901
    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 已提交
6902
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
6903 6904 6905 6906 6907 6908 6909 6910 6911
    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 已提交
6912
    tcg_temp_free_i64(t2);                                                    \
6913 6914 6915 6916 6917 6918 6919 6920
    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 已提交
6921 6922
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6923 6924 6925
}
#else
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
B
Blue Swirl 已提交
6926
static inline void gen_##name(DisasContext *ctx)                              \
6927 6928
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6929
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962
        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 已提交
6963
static inline void gen_brinc(DisasContext *ctx)
6964 6965
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
6966 6967
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6968
}
B
Blue Swirl 已提交
6969
static inline void gen_evmergelo(DisasContext *ctx)
6970 6971
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
6972
        gen_exception(ctx, POWERPC_EXCP_APU);
6973 6974 6975
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6976 6977
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6978
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
6979 6980 6981 6982 6983 6984
    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)]);
6985
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6986 6987
#endif
}
B
Blue Swirl 已提交
6988
static inline void gen_evmergehilo(DisasContext *ctx)
6989 6990
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
6991
        gen_exception(ctx, POWERPC_EXCP_APU);
6992 6993 6994
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6995 6996
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6997
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
6998 6999 7000 7001 7002 7003 7004 7005 7006
    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 已提交
7007
static inline void gen_evmergelohi(DisasContext *ctx)
7008 7009
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7010
        gen_exception(ctx, POWERPC_EXCP_APU);
7011 7012 7013
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7014 7015
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7016 7017 7018 7019 7020 7021
    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
7022 7023 7024 7025 7026 7027 7028 7029 7030 7031
    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)]);
    }
7032 7033
#endif
}
B
Blue Swirl 已提交
7034
static inline void gen_evsplati(DisasContext *ctx)
7035
{
7036
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
7037

7038
#if defined(TARGET_PPC64)
7039
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7040 7041 7042 7043 7044
#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 已提交
7045
static inline void gen_evsplatfi(DisasContext *ctx)
7046
{
7047
    uint64_t imm = rA(ctx->opcode) << 27;
7048

7049
#if defined(TARGET_PPC64)
7050
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7051 7052 7053 7054
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7055 7056
}

B
Blue Swirl 已提交
7057
static inline void gen_evsel(DisasContext *ctx)
7058 7059 7060 7061 7062
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7063
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7064
#if defined(TARGET_PPC64)
P
pbrook 已提交
7065 7066
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085
#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)
7086
    tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
7087 7088 7089 7090 7091 7092
#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)
7093
    tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
7094 7095 7096 7097
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7098
    tcg_temp_free_i32(t0);
7099 7100 7101 7102 7103 7104
#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 已提交
7105 7106

static void gen_evsel0(DisasContext *ctx)
7107 7108 7109
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7110 7111

static void gen_evsel1(DisasContext *ctx)
7112 7113 7114
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7115 7116

static void gen_evsel2(DisasContext *ctx)
7117 7118 7119
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7120 7121

static void gen_evsel3(DisasContext *ctx)
7122 7123 7124
{
    gen_evsel(ctx);
}
7125

7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282
/* Multiply */

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

    if (unlikely(!ctx->spe_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_APU);
        return;
    }

    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();

    /* t0 := rA; t1 := rB */
#if defined(TARGET_PPC64)
    tcg_gen_ext32u_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32u_tl(t1, cpu_gpr[rB(ctx->opcode)]);
#else
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
#endif

    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */

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

    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
}

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

    if (unlikely(!ctx->spe_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_APU);
        return;
    }

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

    tmp = tcg_temp_new_i64();

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

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

    if (unlikely(!ctx->spe_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_APU);
        return;
    }

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

    acc = tcg_temp_new_i64();
    tmp = tcg_temp_new_i64();

    /* tmp := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));

    /* Load acc */
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));

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

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

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

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

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

    if (unlikely(!ctx->spe_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_APU);
        return;
    }

    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();

    /* t0 := rA; t1 := rB */
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
#else
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
#endif

    tcg_gen_mul_i64(t0, t0, t1);  /* t0 := rA * rB */

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

    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
}

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

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

    tmp = tcg_temp_new_i64();

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

    tcg_temp_free_i64(tmp);
}

static inline void gen_evmwsmiaa(DisasContext *ctx)
{
    TCGv_i64 acc = tcg_temp_new_i64();
    TCGv_i64 tmp = tcg_temp_new_i64();

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

    acc = tcg_temp_new_i64();
    tmp = tcg_temp_new_i64();

    /* tmp := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));

    /* Load acc */
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));

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

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

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

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

7283 7284 7285 7286 7287 7288 7289 7290
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); //
7291
GEN_SPE(evmra,          speundef,      0x02, 0x13, 0x0000F800, PPC_SPE);
7292 7293 7294 7295
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); ////
7296 7297 7298
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312
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); ////

7313
/* SPE load and stores */
B
Blue Swirl 已提交
7314
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7315 7316 7317
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7318
    if (rA(ctx->opcode) == 0) {
7319
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7320
    } else {
7321
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
A
aurel32 已提交
7322 7323 7324 7325 7326 7327
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
7328
}
7329

B
Blue Swirl 已提交
7330
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7331 7332
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7333
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7334 7335
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7336
    gen_qemu_ld64(ctx, t0, addr);
7337 7338 7339 7340 7341
    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
7342
}
7343

B
Blue Swirl 已提交
7344
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7345
{
7346
#if defined(TARGET_PPC64)
7347
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7348
    gen_qemu_ld32u(ctx, t0, addr);
7349
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7350 7351
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7352 7353 7354
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7355 7356 7357
    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);
7358
#endif
7359
}
7360

B
Blue Swirl 已提交
7361
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7362 7363 7364
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7365
    gen_qemu_ld16u(ctx, t0, addr);
7366
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7367 7368
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7369 7370
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7371 7372
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7373 7374
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7375 7376
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7377
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7378
#else
A
aurel32 已提交
7379
    gen_qemu_ld16u(ctx, t0, addr);
7380
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7381 7382
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7383
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7384 7385
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7386
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7387 7388
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7389
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7390
#endif
7391
    tcg_temp_free(t0);
7392 7393
}

B
Blue Swirl 已提交
7394
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7395 7396
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7397
    gen_qemu_ld16u(ctx, t0, addr);
7398 7399 7400 7401 7402 7403 7404 7405 7406 7407
#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);
7408 7409
}

B
Blue Swirl 已提交
7410
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7411 7412
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7413
    gen_qemu_ld16u(ctx, t0, addr);
7414 7415 7416 7417 7418 7419 7420 7421
#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);
7422 7423
}

B
Blue Swirl 已提交
7424
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7425 7426
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7427
    gen_qemu_ld16s(ctx, t0, addr);
7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438
#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 已提交
7439
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7440 7441 7442
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7443
    gen_qemu_ld16u(ctx, t0, addr);
7444
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7445 7446
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7447 7448 7449
    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 已提交
7450
    gen_qemu_ld16u(ctx, t0, addr);
7451
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7452 7453
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7454 7455 7456 7457 7458
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7459
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7460 7461 7462
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7463 7464 7465
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7466 7467 7468 7469
    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 已提交
7470 7471 7472
    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);
7473 7474 7475
#endif
}

B
Blue Swirl 已提交
7476
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7477 7478 7479
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7480
    gen_qemu_ld16s(ctx, t0, addr);
7481
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7482 7483
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7484 7485 7486 7487
    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 已提交
7488 7489 7490
    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);
7491 7492 7493
#endif
}

B
Blue Swirl 已提交
7494
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7495 7496
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7497
    gen_qemu_ld32u(ctx, t0, addr);
7498
#if defined(TARGET_PPC64)
7499 7500 7501 7502 7503 7504 7505 7506 7507
    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 已提交
7508
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7509 7510 7511
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7512
    gen_qemu_ld16u(ctx, t0, addr);
7513 7514 7515
    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 已提交
7516 7517
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7518 7519 7520 7521
    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 已提交
7522
    gen_qemu_ld16u(ctx, t0, addr);
7523 7524
    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 已提交
7525 7526
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7527 7528
    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);
7529
#endif
7530 7531 7532
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7533
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7534 7535
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7536
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7537
#else
7538 7539
    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 已提交
7540
    gen_qemu_st64(ctx, t0, addr);
7541 7542 7543 7544
    tcg_temp_free_i64(t0);
#endif
}

B
Blue Swirl 已提交
7545
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7546
{
7547
#if defined(TARGET_PPC64)
7548 7549
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7550
    gen_qemu_st32(ctx, t0, addr);
7551 7552
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7553
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7554
#endif
A
aurel32 已提交
7555 7556
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7557 7558
}

B
Blue Swirl 已提交
7559
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7560 7561 7562 7563 7564 7565 7566
{
    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 已提交
7567 7568
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7569 7570
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7571
    gen_qemu_st16(ctx, t0, addr);
7572
#else
A
aurel32 已提交
7573
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7574
#endif
A
aurel32 已提交
7575
    gen_addr_add(ctx, addr, addr, 2);
7576
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7577
    gen_qemu_st16(ctx, t0, addr);
7578
    tcg_temp_free(t0);
A
aurel32 已提交
7579 7580
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7581 7582
}

B
Blue Swirl 已提交
7583
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7584 7585 7586 7587 7588 7589 7590
{
    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 已提交
7591 7592
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7593
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7594
    gen_qemu_st16(ctx, t0, addr);
7595 7596 7597
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7598
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7599 7600 7601 7602
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7603
    gen_qemu_st16(ctx, t0, addr);
7604 7605
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7606
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7607
#endif
A
aurel32 已提交
7608 7609
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7610 7611
}

B
Blue Swirl 已提交
7612
static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7613 7614 7615 7616
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7617
    gen_qemu_st32(ctx, t0, addr);
7618 7619
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7620
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7621 7622 7623
#endif
}

B
Blue Swirl 已提交
7624
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7625
{
A
aurel32 已提交
7626
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7627 7628 7629
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
B
Blue Swirl 已提交
7630
static void glue(gen_, name)(DisasContext *ctx)                                       \
7631 7632 7633
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7634
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7635 7636
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7637
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7638 7639
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
7640
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7641
    } else {                                                                  \
A
aurel32 已提交
7642
        gen_addr_reg_index(ctx, t0);                                          \
7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666
    }                                                                         \
    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);
7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740

/* 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(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(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(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(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 已提交
7741 7742
#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
7743
static inline void gen_##name(DisasContext *ctx)                              \
7744
{                                                                             \
A
aurel32 已提交
7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756
    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);                                                        \
7757
}
A
aurel32 已提交
7758
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
7759
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773
{                                                                             \
    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 已提交
7774
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7775 7776 7777 7778 7779 7780 7781
{                                                                             \
    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 已提交
7782
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7783 7784 7785 7786
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
7787
static inline void gen_##name(DisasContext *ctx)                              \
7788
{                                                                             \
A
aurel32 已提交
7789 7790
    TCGv_i32 t0, t1;                                                          \
    TCGv_i64 t2;                                                              \
7791
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7792
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7793 7794
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807
    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);                                                        \
7808
}
A
aurel32 已提交
7809
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
7810
static inline void gen_##name(DisasContext *ctx)                              \
7811 7812
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7813
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7814 7815
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7816 7817
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],     \
                      cpu_gpr[rB(ctx->opcode)]);                              \
7818
}
A
aurel32 已提交
7819
#define GEN_SPEFPUOP_COMP_32(name)                                            \
B
Blue Swirl 已提交
7820
static inline void gen_##name(DisasContext *ctx)                              \
7821
{                                                                             \
A
aurel32 已提交
7822
    TCGv_i32 t0, t1;                                                          \
7823
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7824
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7825 7826
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7827 7828 7829 7830 7831 7832 7833 7834 7835
    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 已提交
7836
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7837 7838
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7839
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7840 7841 7842 7843 7844 7845 7846
        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 已提交
7847
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7848 7849
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7850
}
A
aurel32 已提交
7851
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
7852
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7853 7854 7855 7856 7857 7858 7859
{                                                                             \
    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 已提交
7860
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7861 7862 7863 7864 7865 7866 7867
{                                                                             \
    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 已提交
7868
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7869 7870 7871 7872 7873 7874 7875 7876
{                                                                             \
    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 已提交
7877
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7878 7879
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7880
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7881 7882 7883 7884 7885 7886
        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 已提交
7887
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7888 7889 7890
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7891
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903
        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 已提交
7904
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7905 7906
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7907
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7908 7909 7910 7911 7912 7913
        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 已提交
7914
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7915 7916 7917
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7918
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929
        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
7930

7931 7932
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
7933 7934 7935 7936
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 已提交
7937
static inline void gen_evfsabs(DisasContext *ctx)
A
aurel32 已提交
7938 7939
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7940
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7941 7942 7943
        return;
    }
#if defined(TARGET_PPC64)
7944
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
A
aurel32 已提交
7945
#else
7946 7947
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
    tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
A
aurel32 已提交
7948 7949
#endif
}
B
Blue Swirl 已提交
7950
static inline void gen_evfsnabs(DisasContext *ctx)
A
aurel32 已提交
7951 7952
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7953
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7954 7955 7956
        return;
    }
#if defined(TARGET_PPC64)
7957
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
7958
#else
7959 7960
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
    tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
7961 7962
#endif
}
B
Blue Swirl 已提交
7963
static inline void gen_evfsneg(DisasContext *ctx)
A
aurel32 已提交
7964 7965
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7966
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7967 7968 7969
        return;
    }
#if defined(TARGET_PPC64)
7970
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
7971
#else
7972 7973
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
    tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
7974 7975 7976
#endif
}

7977
/* Conversion */
A
aurel32 已提交
7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988
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);

7989
/* Comparison */
A
aurel32 已提交
7990 7991 7992 7993 7994 7995
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);
7996 7997

/* Opcodes definitions */
7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011
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); //
8012 8013 8014

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8015 8016 8017 8018
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 已提交
8019
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
8020 8021
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8022
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8023 8024
        return;
    }
8025
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
A
aurel32 已提交
8026
}
B
Blue Swirl 已提交
8027
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
8028 8029
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8030
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8031 8032
        return;
    }
8033
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8034
}
B
Blue Swirl 已提交
8035
static inline void gen_efsneg(DisasContext *ctx)
A
aurel32 已提交
8036 8037
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8038
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8039 8040
        return;
    }
8041
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8042 8043
}

8044
/* Conversion */
A
aurel32 已提交
8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056
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);

8057
/* Comparison */
A
aurel32 已提交
8058 8059 8060 8061 8062 8063
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);
8064 8065

/* Opcodes definitions */
8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079
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); //
8080 8081 8082

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8083 8084 8085 8086
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 已提交
8087
static inline void gen_efdabs(DisasContext *ctx)
A
aurel32 已提交
8088 8089
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8090
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8091 8092 8093
        return;
    }
#if defined(TARGET_PPC64)
8094
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
A
aurel32 已提交
8095
#else
8096 8097
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
A
aurel32 已提交
8098 8099
#endif
}
B
Blue Swirl 已提交
8100
static inline void gen_efdnabs(DisasContext *ctx)
A
aurel32 已提交
8101 8102
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8103
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8104 8105 8106
        return;
    }
#if defined(TARGET_PPC64)
8107
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8108
#else
8109 8110
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8111 8112
#endif
}
B
Blue Swirl 已提交
8113
static inline void gen_efdneg(DisasContext *ctx)
A
aurel32 已提交
8114 8115
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8116
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8117 8118 8119
        return;
    }
#if defined(TARGET_PPC64)
8120
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8121
#else
8122 8123
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8124 8125 8126
#endif
}

8127
/* Conversion */
A
aurel32 已提交
8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142
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);
8143 8144

/* Comparison */
A
aurel32 已提交
8145 8146 8147 8148 8149 8150
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);
8151 8152

/* Opcodes definitions */
8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168
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); //
8169

A
Anthony Liguori 已提交
8170
static opcode_t opcodes[] = {
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 8202 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
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),
8244
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
8245 8246
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
8247
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
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
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),
8394
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
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 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892
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),
8893
GEN_VXFORM_NOA(vexptefp, 5, 6),
8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931
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),
8932
GEN_SPE(evmra,          speundef,      0x02, 0x13, 0x0000F800, PPC_SPE),
8933 8934 8935 8936
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),
8937 8938 8939
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE),
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE),
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE),
8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024
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),
};

9025
#include "translate_init.c"
9026
#include "helper_regs.h"
B
bellard 已提交
9027

9028
/*****************************************************************************/
9029
/* Misc PowerPC helpers */
9030
void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
9031
                     int flags)
B
bellard 已提交
9032
{
9033 9034 9035
#define RGPL  4
#define RFPL  4

B
bellard 已提交
9036 9037
    int i;

9038
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
9039 9040
                TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
                env->nip, env->lr, env->ctr, env->xer);
9041 9042 9043
    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);
9044
#if !defined(NO_TIMER_DUMP)
9045
    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
9046
#if !defined(CONFIG_USER_ONLY)
9047
                " DECR %08" PRIu32
9048 9049
#endif
                "\n",
J
j_mayer 已提交
9050
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
9051 9052 9053 9054
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
9055
#endif
9056
    for (i = 0; i < 32; i++) {
9057 9058
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
9059
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
9060
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
9061
            cpu_fprintf(f, "\n");
9062
    }
9063
    cpu_fprintf(f, "CR ");
9064
    for (i = 0; i < 8; i++)
B
bellard 已提交
9065 9066
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
9067 9068 9069 9070 9071 9072 9073 9074
    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 已提交
9075
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
9076
    }
9077 9078
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
9079 9080 9081
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
9082
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
9083
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
9084
            cpu_fprintf(f, "\n");
B
bellard 已提交
9085
    }
9086
    cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
9087
#if !defined(CONFIG_USER_ONLY)
9088 9089 9090
    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);
9091
#endif
B
bellard 已提交
9092

9093 9094
#undef RGPL
#undef RFPL
B
bellard 已提交
9095 9096
}

9097
void cpu_dump_statistics (CPUState *env, FILE*f, fprintf_function cpu_fprintf,
9098 9099 9100
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
A
Anthony Liguori 已提交
9101
    opc_handler_t **t1, **t2, **t3, *handler;
9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117
    int op1, op2, op3;

    t1 = env->opcodes;
    for (op1 = 0; op1 < 64; op1++) {
        handler = t1[op1];
        if (is_indirect_opcode(handler)) {
            t2 = ind_table(handler);
            for (op2 = 0; op2 < 32; op2++) {
                handler = t2[op2];
                if (is_indirect_opcode(handler)) {
                    t3 = ind_table(handler);
                    for (op3 = 0; op3 < 32; op3++) {
                        handler = t3[op3];
                        if (handler->count == 0)
                            continue;
                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
B
Blue Swirl 已提交
9118
                                    "%016" PRIx64 " %" PRId64 "\n",
9119 9120 9121 9122 9123 9124 9125 9126
                                    op1, op2, op3, op1, (op3 << 5) | op2,
                                    handler->oname,
                                    handler->count, handler->count);
                    }
                } else {
                    if (handler->count == 0)
                        continue;
                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
B
Blue Swirl 已提交
9127
                                "%016" PRIx64 " %" PRId64 "\n",
9128 9129 9130 9131 9132 9133 9134
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
B
Blue Swirl 已提交
9135 9136
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
                        " %" PRId64 "\n",
9137 9138 9139 9140 9141 9142 9143
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

9144
/*****************************************************************************/
B
Blue Swirl 已提交
9145 9146 9147
static inline void gen_intermediate_code_internal(CPUState *env,
                                                  TranslationBlock *tb,
                                                  int search_pc)
B
bellard 已提交
9148
{
9149
    DisasContext ctx, *ctxp = &ctx;
A
Anthony Liguori 已提交
9150
    opc_handler_t **table, *handler;
B
bellard 已提交
9151
    target_ulong pc_start;
B
bellard 已提交
9152
    uint16_t *gen_opc_end;
9153
    CPUBreakpoint *bp;
B
bellard 已提交
9154
    int j, lj = -1;
P
pbrook 已提交
9155 9156
    int num_insns;
    int max_insns;
B
bellard 已提交
9157 9158 9159

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
9160
    ctx.nip = pc_start;
B
bellard 已提交
9161
    ctx.tb = tb;
9162
    ctx.exception = POWERPC_EXCP_NONE;
9163
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
9164 9165 9166
    ctx.mem_idx = env->mmu_idx;
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
9167 9168
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
9169
#endif
B
bellard 已提交
9170
    ctx.fpu_enabled = msr_fp;
9171
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
9172 9173 9174
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
9175 9176 9177 9178
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
9179
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
9180
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
9181
    else
9182
        ctx.singlestep_enabled = 0;
9183
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
9184 9185 9186
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
9187
#if defined (DO_SINGLE_STEP) && 0
9188 9189 9190
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
9191 9192 9193 9194 9195 9196
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
9197
    /* Set env in case of segfault during code fetch */
9198
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
B
Blue Swirl 已提交
9199 9200
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9201
                if (bp->pc == ctx.nip) {
A
aurel32 已提交
9202
                    gen_debug_exception(ctxp);
9203 9204 9205 9206
                    break;
                }
            }
        }
9207
        if (unlikely(search_pc)) {
B
bellard 已提交
9208 9209 9210 9211 9212 9213
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
            }
9214 9215 9216
            gen_opc_pc[lj] = ctx.nip;
            gen_opc_instr_start[lj] = 1;
            gen_opc_icount[lj] = num_insns;
B
bellard 已提交
9217
        }
9218
        LOG_DISAS("----------------\n");
9219
        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
9220
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
P
pbrook 已提交
9221 9222
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
A
aurel32 已提交
9223
        if (unlikely(ctx.le_mode)) {
9224 9225 9226
            ctx.opcode = bswap32(ldl_code(ctx.nip));
        } else {
            ctx.opcode = ldl_code(ctx.nip);
9227
        }
9228
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9229
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
9230
                    opc3(ctx.opcode), little_endian ? "little" : "big");
9231 9232
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
            tcg_gen_debug_insn_start(ctx.nip);
B
bellard 已提交
9233
        ctx.nip += 4;
9234
        table = env->opcodes;
P
pbrook 已提交
9235
        num_insns++;
B
bellard 已提交
9236 9237 9238 9239 9240 9241 9242 9243 9244 9245
        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 ? */
9246
        if (unlikely(handler->handler == &gen_invalid)) {
9247 9248
            if (qemu_log_enabled()) {
                qemu_log("invalid/unsupported opcode: "
9249 9250 9251
                         "%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 已提交
9252
            }
9253 9254
        } else {
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
9255 9256
                if (qemu_log_enabled()) {
                    qemu_log("invalid bits: %08x for opcode: "
9257 9258 9259 9260
                             "%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);
9261
                }
A
aurel32 已提交
9262
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
B
bellard 已提交
9263
                break;
B
bellard 已提交
9264 9265
            }
        }
B
bellard 已提交
9266
        (*(handler->handler))(&ctx);
9267 9268 9269
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
9270
        /* Check trace mode exceptions */
9271 9272 9273 9274 9275
        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 已提交
9276
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
9277
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
9278
                            (env->singlestep_enabled) ||
9279
                            singlestep ||
P
pbrook 已提交
9280
                            num_insns >= max_insns)) {
9281 9282 9283
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
9284
            break;
9285
        }
9286
    }
P
pbrook 已提交
9287 9288
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
9289
    if (ctx.exception == POWERPC_EXCP_NONE) {
9290
        gen_goto_tb(&ctx, 0, ctx.nip);
9291
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
9292
        if (unlikely(env->singlestep_enabled)) {
A
aurel32 已提交
9293
            gen_debug_exception(ctxp);
9294
        }
9295
        /* Generate the return instruction */
B
bellard 已提交
9296
        tcg_gen_exit_tb(0);
9297
    }
P
pbrook 已提交
9298
    gen_icount_end(tb, num_insns);
B
bellard 已提交
9299
    *gen_opc_ptr = INDEX_op_end;
9300
    if (unlikely(search_pc)) {
9301 9302 9303 9304 9305
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
B
bellard 已提交
9306
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
9307
        tb->icount = num_insns;
9308
    }
9309
#if defined(DEBUG_DISAS)
9310
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9311
        int flags;
9312
        flags = env->bfd_mach;
A
aurel32 已提交
9313
        flags |= ctx.le_mode << 16;
9314 9315 9316
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
        log_target_disas(pc_start, ctx.nip - pc_start, flags);
        qemu_log("\n");
9317
    }
B
bellard 已提交
9318 9319 9320
#endif
}

9321
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
9322
{
9323
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
9324 9325
}

9326
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
9327
{
9328
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
9329
}
A
aurel32 已提交
9330 9331 9332 9333 9334 9335

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