translate.c 340.3 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 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256
static void gen_slbmfee(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
        return;
    }
    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)],
                             cpu_gpr[rB(ctx->opcode)]);
#endif
}

static void gen_slbmfev(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
        return;
    }
    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)],
                             cpu_gpr[rB(ctx->opcode)]);
#endif
}
4257 4258
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4259
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4260
/* Optional & mem_idx only: */
B
Blue Swirl 已提交
4261

4262
/* tlbia */
B
Blue Swirl 已提交
4263
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4264
{
4265
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4266
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4267
#else
A
aurel32 已提交
4268
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4269
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4270
        return;
4271
    }
4272
    gen_helper_tlbia();
4273
#endif
B
bellard 已提交
4274 4275
}

B
blueswir1 已提交
4276
/* tlbiel */
B
Blue Swirl 已提交
4277
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289
{
#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 已提交
4290
/* tlbie */
B
Blue Swirl 已提交
4291
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4292
{
4293
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4294
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4295
#else
A
aurel32 已提交
4296
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4297
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4298
        return;
4299
    }
4300
#if defined(TARGET_PPC64)
4301 4302 4303 4304 4305 4306
    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
4307
#endif
4308
        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4309
#endif
B
bellard 已提交
4310 4311 4312
}

/* tlbsync */
B
Blue Swirl 已提交
4313
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4314
{
4315
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4316
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4317
#else
A
aurel32 已提交
4318
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4319
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4320
        return;
4321 4322 4323 4324
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4325
    gen_stop_exception(ctx);
4326
#endif
B
bellard 已提交
4327 4328
}

J
j_mayer 已提交
4329 4330
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4331
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4332 4333
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4334
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4335
#else
A
aurel32 已提交
4336
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4337
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4338 4339
        return;
    }
4340
    gen_helper_slbia();
J
j_mayer 已提交
4341 4342 4343 4344
#endif
}

/* slbie */
B
Blue Swirl 已提交
4345
static void gen_slbie(DisasContext *ctx)
J
j_mayer 已提交
4346 4347
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4348
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4349
#else
A
aurel32 已提交
4350
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4351
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4352 4353
        return;
    }
4354
    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4355 4356 4357 4358
#endif
}
#endif

B
bellard 已提交
4359 4360
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4361

4362
/* eciwx */
B
Blue Swirl 已提交
4363
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4364
{
A
aurel32 已提交
4365
    TCGv t0;
4366
    /* Should check EAR[E] ! */
A
aurel32 已提交
4367 4368 4369
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4370
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4371
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4372
    tcg_temp_free(t0);
4373 4374 4375
}

/* ecowx */
B
Blue Swirl 已提交
4376
static void gen_ecowx(DisasContext *ctx)
4377
{
A
aurel32 已提交
4378
    TCGv t0;
4379
    /* Should check EAR[E] ! */
A
aurel32 已提交
4380 4381 4382
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4383
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4384
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4385
    tcg_temp_free(t0);
4386 4387 4388
}

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

4390
/* abs - abs. */
B
Blue Swirl 已提交
4391
static void gen_abs(DisasContext *ctx)
4392
{
4393 4394 4395 4396 4397 4398 4399 4400
    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);
4401
    if (unlikely(Rc(ctx->opcode) != 0))
4402
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4403 4404 4405
}

/* abso - abso. */
B
Blue Swirl 已提交
4406
static void gen_abso(DisasContext *ctx)
4407
{
4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422
    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);
4423
    if (unlikely(Rc(ctx->opcode) != 0))
4424
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4425 4426 4427
}

/* clcs */
B
Blue Swirl 已提交
4428
static void gen_clcs(DisasContext *ctx)
4429
{
4430 4431 4432
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
4433
    /* Rc=1 sets CR0 to an undefined state */
4434 4435 4436
}

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

/* divo - divo. */
B
Blue Swirl 已提交
4445
static void gen_divo(DisasContext *ctx)
4446
{
4447
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4448
    if (unlikely(Rc(ctx->opcode) != 0))
4449
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4450 4451 4452
}

/* divs - divs. */
B
Blue Swirl 已提交
4453
static void gen_divs(DisasContext *ctx)
4454
{
4455
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4456
    if (unlikely(Rc(ctx->opcode) != 0))
4457
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4458 4459 4460
}

/* divso - divso. */
B
Blue Swirl 已提交
4461
static void gen_divso(DisasContext *ctx)
4462
{
4463
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4464
    if (unlikely(Rc(ctx->opcode) != 0))
4465
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4466 4467 4468
}

/* doz - doz. */
B
Blue Swirl 已提交
4469
static void gen_doz(DisasContext *ctx)
4470
{
4471 4472 4473 4474 4475 4476 4477 4478
    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);
4479
    if (unlikely(Rc(ctx->opcode) != 0))
4480
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4481 4482 4483
}

/* dozo - dozo. */
B
Blue Swirl 已提交
4484
static void gen_dozo(DisasContext *ctx)
4485
{
4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507
    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);
4508
    if (unlikely(Rc(ctx->opcode) != 0))
4509
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4510 4511 4512
}

/* dozi */
B
Blue Swirl 已提交
4513
static void gen_dozi(DisasContext *ctx)
4514
{
4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525
    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)]);
4526 4527 4528
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4529
static void gen_lscbx(DisasContext *ctx)
4530
{
4531 4532 4533 4534
    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));
4535

A
aurel32 已提交
4536
    gen_addr_reg_index(ctx, t0);
4537
    /* NIP cannot be restored if the memory exception comes from an helper */
4538
    gen_update_nip(ctx, ctx->nip - 4);
4539 4540 4541 4542
    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 已提交
4543
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4544
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4545
    if (unlikely(Rc(ctx->opcode) != 0))
4546 4547
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4548 4549 4550
}

/* maskg - maskg. */
B
Blue Swirl 已提交
4551
static void gen_maskg(DisasContext *ctx)
4552
{
4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571
    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);
4572
    if (unlikely(Rc(ctx->opcode) != 0))
4573
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4574 4575 4576
}

/* maskir - maskir. */
B
Blue Swirl 已提交
4577
static void gen_maskir(DisasContext *ctx)
4578
{
4579 4580 4581 4582 4583 4584 4585
    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);
4586
    if (unlikely(Rc(ctx->opcode) != 0))
4587
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4588 4589 4590
}

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

/* mulo - mulo. */
B
Blue Swirl 已提交
4611
static void gen_mulo(DisasContext *ctx)
4612
{
4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632
    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);
4633
    if (unlikely(Rc(ctx->opcode) != 0))
4634
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4635 4636 4637
}

/* nabs - nabs. */
B
Blue Swirl 已提交
4638
static void gen_nabs(DisasContext *ctx)
4639
{
4640 4641 4642 4643 4644 4645 4646 4647
    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);
4648
    if (unlikely(Rc(ctx->opcode) != 0))
4649
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4650 4651 4652
}

/* nabso - nabso. */
B
Blue Swirl 已提交
4653
static void gen_nabso(DisasContext *ctx)
4654
{
4655 4656 4657 4658 4659 4660 4661 4662 4663 4664
    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));
4665
    if (unlikely(Rc(ctx->opcode) != 0))
4666
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4667 4668 4669
}

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

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

/* sle - sle. */
B
Blue Swirl 已提交
4704
static void gen_sle(DisasContext *ctx)
4705
{
4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716
    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);
4717
    if (unlikely(Rc(ctx->opcode) != 0))
4718
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4719 4720 4721
}

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

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

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

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

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

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

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

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

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

/* sreq */
B
Blue Swirl 已提交
4920
static void gen_sreq(DisasContext *ctx)
4921
{
4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936
    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);
4937
    if (unlikely(Rc(ctx->opcode) != 0))
4938
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4939 4940 4941
}

/* sriq */
B
Blue Swirl 已提交
4942
static void gen_sriq(DisasContext *ctx)
4943
{
4944 4945 4946 4947 4948 4949 4950 4951 4952 4953
    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);
4954
    if (unlikely(Rc(ctx->opcode) != 0))
4955
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4956 4957 4958
}

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

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

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

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

5031
/* dsa  */
B
Blue Swirl 已提交
5032
static void gen_dsa(DisasContext *ctx)
5033 5034
{
    /* XXX: TODO */
A
aurel32 已提交
5035
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5036 5037 5038
}

/* esa */
B
Blue Swirl 已提交
5039
static void gen_esa(DisasContext *ctx)
5040 5041
{
    /* XXX: TODO */
A
aurel32 已提交
5042
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5043 5044 5045
}

/* mfrom */
B
Blue Swirl 已提交
5046
static void gen_mfrom(DisasContext *ctx)
5047 5048
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5049
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5050
#else
A
aurel32 已提交
5051
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5052
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5053 5054
        return;
    }
5055
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5056 5057 5058 5059
#endif
}

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

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

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

5089
/* 74xx TLB management */
B
Blue Swirl 已提交
5090

5091
/* tlbld */
B
Blue Swirl 已提交
5092
static void gen_tlbld_74xx(DisasContext *ctx)
5093 5094
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5095
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5096
#else
A
aurel32 已提交
5097
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5098
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5099 5100
        return;
    }
5101
    gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5102 5103 5104 5105
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5106
static void gen_tlbli_74xx(DisasContext *ctx)
5107 5108
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5109
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5110
#else
A
aurel32 已提交
5111
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5112
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5113 5114
        return;
    }
5115
    gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5116 5117 5118
#endif
}

5119
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5120

5121
/* clf */
B
Blue Swirl 已提交
5122
static void gen_clf(DisasContext *ctx)
5123 5124 5125 5126 5127
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5128
static void gen_cli(DisasContext *ctx)
5129
{
B
blueswir1 已提交
5130
    /* Cache line invalidate: privileged and treated as no-op */
5131
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5132
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5133
#else
A
aurel32 已提交
5134
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5135
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5136 5137 5138 5139 5140 5141
        return;
    }
#endif
}

/* dclst */
B
Blue Swirl 已提交
5142
static void gen_dclst(DisasContext *ctx)
5143 5144 5145 5146
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5147
static void gen_mfsri(DisasContext *ctx)
5148 5149
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5150
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5151
#else
5152 5153 5154
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5155
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5156
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5157 5158
        return;
    }
5159
    t0 = tcg_temp_new();
A
aurel32 已提交
5160
    gen_addr_reg_index(ctx, t0);
5161 5162 5163 5164
    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);
5165
    if (ra != 0 && ra != rd)
5166
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5167 5168 5169
#endif
}

B
Blue Swirl 已提交
5170
static void gen_rac(DisasContext *ctx)
5171 5172
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5173
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5174
#else
5175
    TCGv t0;
A
aurel32 已提交
5176
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5177
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5178 5179
        return;
    }
5180
    t0 = tcg_temp_new();
A
aurel32 已提交
5181
    gen_addr_reg_index(ctx, t0);
5182 5183
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
5184 5185 5186
#endif
}

B
Blue Swirl 已提交
5187
static void gen_rfsvc(DisasContext *ctx)
5188 5189
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5190
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5191
#else
A
aurel32 已提交
5192
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5193
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5194 5195
        return;
    }
5196
    gen_helper_rfsvc();
A
aurel32 已提交
5197
    gen_sync_exception(ctx);
5198 5199 5200 5201 5202 5203 5204 5205 5206
#endif
}

/* svc is not implemented for now */

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

/* lfq */
B
Blue Swirl 已提交
5207
static void gen_lfq(DisasContext *ctx)
5208
{
5209
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5210 5211 5212 5213 5214 5215 5216
    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);
5217
    tcg_temp_free(t0);
5218 5219 5220
}

/* lfqu */
B
Blue Swirl 已提交
5221
static void gen_lfqu(DisasContext *ctx)
5222 5223
{
    int ra = rA(ctx->opcode);
5224
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5225 5226 5227 5228 5229 5230 5231 5232
    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);
5233
    if (ra != 0)
5234 5235 5236
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5237 5238 5239
}

/* lfqux */
B
Blue Swirl 已提交
5240
static void gen_lfqux(DisasContext *ctx)
5241 5242
{
    int ra = rA(ctx->opcode);
5243
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5244 5245 5246 5247 5248 5249 5250 5251 5252
    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);
5253
    if (ra != 0)
5254 5255
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5256 5257 5258
}

/* lfqx */
B
Blue Swirl 已提交
5259
static void gen_lfqx(DisasContext *ctx)
5260
{
5261
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5262 5263 5264 5265 5266 5267 5268
    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);
5269
    tcg_temp_free(t0);
5270 5271 5272
}

/* stfq */
B
Blue Swirl 已提交
5273
static void gen_stfq(DisasContext *ctx)
5274
{
5275
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5276 5277 5278 5279 5280 5281 5282
    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);
5283
    tcg_temp_free(t0);
5284 5285 5286
}

/* stfqu */
B
Blue Swirl 已提交
5287
static void gen_stfqu(DisasContext *ctx)
5288 5289
{
    int ra = rA(ctx->opcode);
5290
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5291 5292 5293 5294 5295 5296 5297 5298 5299
    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);
5300
    if (ra != 0)
5301 5302
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5303 5304 5305
}

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

/* stfqx */
B
Blue Swirl 已提交
5325
static void gen_stfqx(DisasContext *ctx)
5326
{
5327
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5328 5329 5330 5331 5332 5333 5334
    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);
5335
    tcg_temp_free(t0);
5336 5337 5338
}

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

5340
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5341
static void gen_mfapidi(DisasContext *ctx)
5342 5343
{
    /* XXX: TODO */
A
aurel32 已提交
5344
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5345 5346
}

5347
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5348
static void gen_tlbiva(DisasContext *ctx)
5349 5350
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5351
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5352
#else
5353
    TCGv t0;
A
aurel32 已提交
5354
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5355
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5356 5357
        return;
    }
5358
    t0 = tcg_temp_new();
A
aurel32 已提交
5359
    gen_addr_reg_index(ctx, t0);
5360 5361
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(t0);
5362 5363 5364 5365
#endif
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5366 5367
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5368
{
5369 5370
    TCGv t0, t1;

P
pbrook 已提交
5371 5372
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5373

5374 5375 5376 5377 5378 5379 5380
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5381 5382 5383
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5384 5385 5386 5387 5388
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5389 5390 5391
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5392 5393 5394 5395 5396 5397 5398
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5399 5400 5401 5402
        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);
5403 5404 5405 5406 5407
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5408 5409 5410 5411
        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);
5412 5413 5414 5415 5416 5417 5418
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5419 5420
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5421 5422 5423 5424 5425
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5426 5427
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5428 5429 5430
        break;
    }
    if (opc2 & 0x04) {
5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454
        /* (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 已提交
5455
                if (opc3 & 0x02) {
5456 5457 5458 5459 5460 5461 5462
                    /* 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 已提交
5463
                if (opc3 & 0x02) {
5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476
                    /* 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);
5477
    }
5478 5479
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5480 5481
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5482
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5483 5484 5485
    }
}

5486
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5487
static void glue(gen_, name)(DisasContext *ctx)                               \
5488 5489 5490 5491 5492 5493
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5494
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5495
/* macchwo   - macchwo.   */
5496
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5497
/* macchws   - macchws.   */
5498
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5499
/* macchwso  - macchwso.  */
5500
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5501
/* macchwsu  - macchwsu.  */
5502
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5503
/* macchwsuo - macchwsuo. */
5504
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5505
/* macchwu   - macchwu.   */
5506
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5507
/* macchwuo  - macchwuo.  */
5508
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5509
/* machhw    - machhw.    */
5510
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5511
/* machhwo   - machhwo.   */
5512
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5513
/* machhws   - machhws.   */
5514
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5515
/* machhwso  - machhwso.  */
5516
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5517
/* machhwsu  - machhwsu.  */
5518
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5519
/* machhwsuo - machhwsuo. */
5520
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5521
/* machhwu   - machhwu.   */
5522
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5523
/* machhwuo  - machhwuo.  */
5524
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5525
/* maclhw    - maclhw.    */
5526
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5527
/* maclhwo   - maclhwo.   */
5528
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5529
/* maclhws   - maclhws.   */
5530
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5531
/* maclhwso  - maclhwso.  */
5532
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5533
/* maclhwu   - maclhwu.   */
5534
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5535
/* maclhwuo  - maclhwuo.  */
5536
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5537
/* maclhwsu  - maclhwsu.  */
5538
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5539
/* maclhwsuo - maclhwsuo. */
5540
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5541
/* nmacchw   - nmacchw.   */
5542
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5543
/* nmacchwo  - nmacchwo.  */
5544
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5545
/* nmacchws  - nmacchws.  */
5546
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5547
/* nmacchwso - nmacchwso. */
5548
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5549
/* nmachhw   - nmachhw.   */
5550
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5551
/* nmachhwo  - nmachhwo.  */
5552
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5553
/* nmachhws  - nmachhws.  */
5554
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5555
/* nmachhwso - nmachhwso. */
5556
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5557
/* nmaclhw   - nmaclhw.   */
5558
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5559
/* nmaclhwo  - nmaclhwo.  */
5560
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5561
/* nmaclhws  - nmaclhws.  */
5562
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5563
/* nmaclhwso - nmaclhwso. */
5564
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5565 5566

/* mulchw  - mulchw.  */
5567
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5568
/* mulchwu - mulchwu. */
5569
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5570
/* mulhhw  - mulhhw.  */
5571
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5572
/* mulhhwu - mulhhwu. */
5573
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5574
/* mullhw  - mullhw.  */
5575
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5576
/* mullhwu - mullhwu. */
5577
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5578 5579

/* mfdcr */
B
Blue Swirl 已提交
5580
static void gen_mfdcr(DisasContext *ctx)
5581 5582
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5583
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5584
#else
5585
    TCGv dcrn;
A
aurel32 已提交
5586
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5587
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5588 5589
        return;
    }
5590 5591 5592 5593 5594
    /* 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);
5595 5596 5597 5598
#endif
}

/* mtdcr */
B
Blue Swirl 已提交
5599
static void gen_mtdcr(DisasContext *ctx)
5600 5601
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5602
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5603
#else
5604
    TCGv dcrn;
A
aurel32 已提交
5605
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5606
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5607 5608
        return;
    }
5609 5610 5611 5612 5613
    /* 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);
5614 5615 5616 5617
#endif
}

/* mfdcrx */
5618
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5619
static void gen_mfdcrx(DisasContext *ctx)
5620 5621
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5622
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5623
#else
A
aurel32 已提交
5624
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5625
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5626 5627
        return;
    }
5628 5629 5630
    /* 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)]);
5631
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5632 5633 5634 5635
#endif
}

/* mtdcrx */
5636
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5637
static void gen_mtdcrx(DisasContext *ctx)
5638 5639
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5640
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5641
#else
A
aurel32 已提交
5642
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5643
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5644 5645
        return;
    }
5646 5647 5648
    /* 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)]);
5649
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5650 5651 5652
#endif
}

5653
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5654
static void gen_mfdcrux(DisasContext *ctx)
5655
{
5656 5657 5658
    /* 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)]);
5659 5660 5661 5662
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5663
static void gen_mtdcrux(DisasContext *ctx)
5664
{
5665 5666 5667
    /* 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)]);
5668 5669 5670
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5671
/* dccci */
B
Blue Swirl 已提交
5672
static void gen_dccci(DisasContext *ctx)
5673 5674
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5675
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5676
#else
A
aurel32 已提交
5677
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5678
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5679 5680 5681 5682 5683 5684 5685
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
B
Blue Swirl 已提交
5686
static void gen_dcread(DisasContext *ctx)
5687 5688
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5689
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5690
#else
A
aurel32 已提交
5691
    TCGv EA, val;
A
aurel32 已提交
5692
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5693
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5694 5695
        return;
    }
A
aurel32 已提交
5696
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5697
    EA = tcg_temp_new();
A
aurel32 已提交
5698
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5699
    val = tcg_temp_new();
A
aurel32 已提交
5700
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5701 5702 5703
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5704 5705 5706 5707
#endif
}

/* icbt */
B
Blue Swirl 已提交
5708
static void gen_icbt_40x(DisasContext *ctx)
5709 5710 5711 5712 5713 5714 5715 5716
{
    /* 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 已提交
5717
static void gen_iccci(DisasContext *ctx)
5718 5719
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5720
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5721
#else
A
aurel32 已提交
5722
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5723
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5724 5725 5726 5727 5728 5729 5730
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
B
Blue Swirl 已提交
5731
static void gen_icread(DisasContext *ctx)
5732 5733
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5734
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5735
#else
A
aurel32 已提交
5736
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5737
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5738 5739 5740 5741 5742 5743
        return;
    }
    /* interpreted as no-op */
#endif
}

A
aurel32 已提交
5744
/* rfci (mem_idx only) */
B
Blue Swirl 已提交
5745
static void gen_rfci_40x(DisasContext *ctx)
5746 5747
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5748
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5749
#else
A
aurel32 已提交
5750
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5751
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5752 5753 5754
        return;
    }
    /* Restore CPU state */
5755
    gen_helper_40x_rfci();
A
aurel32 已提交
5756
    gen_sync_exception(ctx);
5757 5758 5759
#endif
}

B
Blue Swirl 已提交
5760
static void gen_rfci(DisasContext *ctx)
5761 5762
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5763
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5764
#else
A
aurel32 已提交
5765
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5766
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5767 5768 5769
        return;
    }
    /* Restore CPU state */
5770
    gen_helper_rfci();
A
aurel32 已提交
5771
    gen_sync_exception(ctx);
5772 5773 5774 5775
#endif
}

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

5777
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5778
static void gen_rfdi(DisasContext *ctx)
5779 5780
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5781
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5782
#else
A
aurel32 已提交
5783
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5784
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5785 5786 5787
        return;
    }
    /* Restore CPU state */
5788
    gen_helper_rfdi();
A
aurel32 已提交
5789
    gen_sync_exception(ctx);
5790 5791 5792
#endif
}

5793
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5794
static void gen_rfmci(DisasContext *ctx)
5795 5796
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5797
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5798
#else
A
aurel32 已提交
5799
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5800
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5801 5802 5803
        return;
    }
    /* Restore CPU state */
5804
    gen_helper_rfmci();
A
aurel32 已提交
5805
    gen_sync_exception(ctx);
5806 5807
#endif
}
5808

5809
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5810

5811
/* tlbre */
B
Blue Swirl 已提交
5812
static void gen_tlbre_40x(DisasContext *ctx)
5813 5814
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5815
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5816
#else
A
aurel32 已提交
5817
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5818
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5819 5820 5821 5822
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5823
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5824 5825
        break;
    case 1:
5826
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5827 5828
        break;
    default:
A
aurel32 已提交
5829
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5830
        break;
5831
    }
5832 5833 5834
#endif
}

5835
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5836
static void gen_tlbsx_40x(DisasContext *ctx)
5837 5838
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5839
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5840
#else
5841
    TCGv t0;
A
aurel32 已提交
5842
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5843
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5844 5845
        return;
    }
5846
    t0 = tcg_temp_new();
A
aurel32 已提交
5847
    gen_addr_reg_index(ctx, t0);
5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858
    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);
    }
5859
#endif
B
bellard 已提交
5860 5861
}

5862
/* tlbwe */
B
Blue Swirl 已提交
5863
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
5864
{
5865
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5866
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5867
#else
A
aurel32 已提交
5868
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5869
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5870 5871 5872 5873
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5874
        gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5875 5876
        break;
    case 1:
5877
        gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5878 5879
        break;
    default:
A
aurel32 已提交
5880
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5881
        break;
5882
    }
5883 5884 5885
#endif
}

5886
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
5887

5888
/* tlbre */
B
Blue Swirl 已提交
5889
static void gen_tlbre_440(DisasContext *ctx)
5890 5891
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5892
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5893
#else
A
aurel32 已提交
5894
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5895
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5896 5897 5898 5899 5900 5901
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5902 5903
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
E
Edgar E. Iglesias 已提交
5904
            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], t0, cpu_gpr[rA(ctx->opcode)]);
5905 5906
            tcg_temp_free_i32(t0);
        }
5907 5908
        break;
    default:
A
aurel32 已提交
5909
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5910 5911 5912 5913 5914 5915
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5916
static void gen_tlbsx_440(DisasContext *ctx)
5917 5918
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5919
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5920
#else
5921
    TCGv t0;
A
aurel32 已提交
5922
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5923
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5924 5925
        return;
    }
5926
    t0 = tcg_temp_new();
A
aurel32 已提交
5927
    gen_addr_reg_index(ctx, t0);
5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938
    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);
    }
5939 5940 5941 5942
#endif
}

/* tlbwe */
B
Blue Swirl 已提交
5943
static void gen_tlbwe_440(DisasContext *ctx)
5944 5945
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5946
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5947
#else
A
aurel32 已提交
5948
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5949
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5950 5951 5952 5953 5954 5955
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5956 5957 5958 5959 5960
        {
            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);
        }
5961 5962
        break;
    default:
A
aurel32 已提交
5963
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5964 5965 5966 5967 5968
        break;
    }
#endif
}

5969
/* wrtee */
B
Blue Swirl 已提交
5970
static void gen_wrtee(DisasContext *ctx)
5971 5972
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5973
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5974
#else
5975
    TCGv t0;
A
aurel32 已提交
5976
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5977
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5978 5979
        return;
    }
5980 5981 5982 5983 5984
    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 已提交
5985 5986 5987
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
5988
    gen_stop_exception(ctx);
5989 5990 5991 5992
#endif
}

/* wrteei */
B
Blue Swirl 已提交
5993
static void gen_wrteei(DisasContext *ctx)
5994 5995
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5996
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5997
#else
A
aurel32 已提交
5998
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5999
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6000 6001
        return;
    }
6002
    if (ctx->opcode & 0x00008000) {
6003 6004
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6005
        gen_stop_exception(ctx);
6006
    } else {
A
aurel32 已提交
6007
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6008
    }
6009 6010 6011
#endif
}

J
j_mayer 已提交
6012
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
6013

6014
/* dlmzb */
B
Blue Swirl 已提交
6015
static void gen_dlmzb(DisasContext *ctx)
6016
{
6017 6018 6019 6020
    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);
6021 6022 6023
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
6024
static void gen_mbar(DisasContext *ctx)
6025 6026 6027 6028 6029
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
B
Blue Swirl 已提交
6030
static void gen_msync(DisasContext *ctx)
6031 6032 6033 6034 6035
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6036
static void gen_icbt_440(DisasContext *ctx)
6037 6038 6039 6040 6041
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6042 6043
}

6044 6045 6046
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

B
Blue Swirl 已提交
6047
static inline TCGv_ptr gen_avr_ptr(int reg)
A
aurel32 已提交
6048
{
A
aurel32 已提交
6049
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6050 6051 6052 6053
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

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

#define GEN_VR_STX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6079
static void gen_st##name(DisasContext *ctx)                                   \
6080
{                                                                             \
6081
    TCGv EA;                                                                  \
6082
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6083
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6084 6085
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6086
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6087
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6088
    gen_addr_reg_index(ctx, EA);                                              \
6089
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6090 6091
    if (ctx->le_mode) {                                                       \
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6092
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6093
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6094
    } else {                                                                  \
A
aurel32 已提交
6095
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6096
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6097
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6098 6099
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6100 6101
}

A
aurel32 已提交
6102
#define GEN_VR_LVE(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6103
static void gen_lve##name(DisasContext *ctx)                            \
A
aurel32 已提交
6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120
    {                                                                   \
        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 已提交
6121
static void gen_stve##name(DisasContext *ctx)                           \
A
aurel32 已提交
6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137
    {                                                                   \
        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);                                          \
    }

6138
GEN_VR_LDX(lvx, 0x07, 0x03);
6139
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6140
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6141

A
aurel32 已提交
6142 6143 6144 6145
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6146
GEN_VR_STX(svx, 0x07, 0x07);
6147
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6148
GEN_VR_STX(svxl, 0x07, 0x0F);
6149

A
aurel32 已提交
6150 6151 6152 6153
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

B
Blue Swirl 已提交
6154
static void gen_lvsl(DisasContext *ctx)
A
aurel32 已提交
6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169
{
    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 已提交
6170
static void gen_lvsr(DisasContext *ctx)
A
aurel32 已提交
6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185
{
    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 已提交
6186
static void gen_mfvscr(DisasContext *ctx)
6187 6188 6189 6190 6191 6192 6193 6194 6195 6196
{
    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);
6197
    tcg_temp_free_i32(t);
6198 6199
}

B
Blue Swirl 已提交
6200
static void gen_mtvscr(DisasContext *ctx)
6201
{
A
aurel32 已提交
6202
    TCGv_ptr p;
6203 6204 6205 6206
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6207 6208 6209
    p = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_mtvscr(p);
    tcg_temp_free_ptr(p);
6210 6211
}

6212 6213
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
B
Blue Swirl 已提交
6214
static void glue(gen_, name)(DisasContext *ctx)                                 \
6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229
{                                                                       \
    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);

6230
#define GEN_VXFORM(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6231
static void glue(gen_, name)(DisasContext *ctx)                                 \
6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246
{                                                                       \
    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 已提交
6247 6248 6249 6250 6251 6252
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);
6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264
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 已提交
6265 6266 6267 6268 6269 6270
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 已提交
6271 6272 6273 6274 6275 6276
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 已提交
6277 6278 6279 6280 6281 6282 6283 6284
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 已提交
6285 6286 6287
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6288 6289 6290 6291 6292 6293
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 已提交
6294 6295
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6296 6297
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309
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 已提交
6310 6311 6312
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6313 6314
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6315 6316 6317 6318 6319 6320 6321 6322
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 已提交
6323
GEN_VXFORM(vpkpx, 7, 12);
6324 6325 6326 6327 6328
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);
6329 6330
GEN_VXFORM(vaddfp, 5, 0);
GEN_VXFORM(vsubfp, 5, 1);
6331 6332
GEN_VXFORM(vmaxfp, 5, 16);
GEN_VXFORM(vminfp, 5, 17);
A
aurel32 已提交
6333

6334
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
B
Blue Swirl 已提交
6335
static void glue(gen_, name)(DisasContext *ctx)                         \
6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354
    {                                                                   \
        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)))

6355 6356 6357 6358 6359 6360 6361 6362 6363
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)
6364 6365 6366 6367
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6368

A
aurel32 已提交
6369
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6370
static void glue(gen_, name)(DisasContext *ctx)                         \
A
aurel32 已提交
6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388
    {                                                                   \
        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);

6389
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
B
Blue Swirl 已提交
6390
static void glue(gen_, name)(DisasContext *ctx)                                 \
6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403
    {                                                                   \
        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 已提交
6404 6405 6406 6407
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 已提交
6408 6409
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
A
aurel32 已提交
6410
GEN_VXFORM_NOA(vrefp, 5, 4);
A
aurel32 已提交
6411
GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
6412
GEN_VXFORM_NOA(vexptefp, 5, 6);
6413
GEN_VXFORM_NOA(vlogefp, 5, 7);
A
aurel32 已提交
6414 6415 6416 6417
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 已提交
6418

6419
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6420
static void glue(gen_, name)(DisasContext *ctx)                                 \
6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434
    {                                                                   \
        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);                                          \
    }

6435
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6436
static void glue(gen_, name)(DisasContext *ctx)                                 \
6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452
    {                                                                   \
        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 已提交
6453 6454 6455
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
A
aurel32 已提交
6456 6457
GEN_VXFORM_UIMM(vcfux, 5, 12);
GEN_VXFORM_UIMM(vcfsx, 5, 13);
6458 6459
GEN_VXFORM_UIMM(vctuxs, 5, 14);
GEN_VXFORM_UIMM(vctsxs, 5, 15);
A
aurel32 已提交
6460

B
Blue Swirl 已提交
6461
static void gen_vsldoi(DisasContext *ctx)
A
aurel32 已提交
6462 6463
{
    TCGv_ptr ra, rb, rd;
6464
    TCGv_i32 sh;
A
aurel32 已提交
6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476
    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);
6477
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6478 6479
}

6480
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
B
Blue Swirl 已提交
6481
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                      \
6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502
    {                                                                   \
        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 已提交
6503 6504
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

B
Blue Swirl 已提交
6505
static void gen_vmladduhm(DisasContext *ctx)
A
aurel32 已提交
6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522
{
    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 已提交
6523
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6524
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6525
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6526
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6527
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6528

6529 6530
/***                           SPE extension                               ***/
/* Register moves */
6531

6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564

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 已提交
6565 6566
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
A
aurel32 已提交
6567 6568 6569
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
6570
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6571
#endif
A
aurel32 已提交
6572
}
6573

B
Blue Swirl 已提交
6574 6575
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
6576 6577 6578
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6579
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6580 6581 6582
    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 已提交
6583
    tcg_temp_free_i64(tmp);
6584
#endif
A
aurel32 已提交
6585
}
6586

6587
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
B
Blue Swirl 已提交
6588
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
6589 6590 6591 6592 6593 6594 6595 6596
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
6597
static inline void gen_speundef(DisasContext *ctx)
6598
{
A
aurel32 已提交
6599
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6600 6601
}

6602 6603 6604
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6605
static inline void gen_##name(DisasContext *ctx)                              \
6606 6607
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6608
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6609 6610
        return;                                                               \
    }                                                                         \
6611 6612 6613 6614 6615
    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 已提交
6616
static inline void gen_##name(DisasContext *ctx)                              \
6617 6618
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6619
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6620 6621 6622 6623 6624 6625
        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)]);                                        \
6626
}
6627 6628 6629 6630 6631 6632 6633 6634 6635 6636
#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);
6637

6638 6639 6640
/* SPE logic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6641
static inline void gen_##name(DisasContext *ctx)                              \
6642 6643
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6644
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6645 6646
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6647 6648 6649
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6650 6651 6652 6653
    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 已提交
6654
    tcg_temp_free_i64(t2);                                                    \
6655 6656
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6657 6658
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6659
}
6660 6661
#else
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
B
Blue Swirl 已提交
6662
static inline void gen_##name(DisasContext *ctx)                              \
6663 6664
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6665
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6666 6667
        return;                                                               \
    }                                                                         \
6668 6669 6670 6671
    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));                                                 \
6672
}
6673 6674 6675 6676 6677
#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);
6678

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

B
Blue Swirl 已提交
6714
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
6715 6716 6717
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
6718

6719 6720 6721 6722
    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 已提交
6723
    tcg_gen_mov_i32(ret, arg1);
6724 6725 6726 6727 6728 6729
    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 已提交
6730
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
6731
{
6732 6733 6734 6735
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
6736 6737
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6738

6739 6740
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6741
static inline void gen_##name(DisasContext *ctx)                              \
6742 6743
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6744
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6745 6746
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6747 6748 6749
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
6750
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
6751 6752 6753 6754 6755 6756 6757
    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 已提交
6758
    tcg_temp_free_i64(t3);                                                    \
6759
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
6760
    tcg_temp_free_i32(t2);                                                    \
6761
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6762 6763
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6764
}
6765 6766
#else
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6767
static inline void gen_##name(DisasContext *ctx)                              \
6768 6769
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6770
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6771 6772
        return;                                                               \
    }                                                                         \
6773 6774 6775 6776
    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)]);                                        \
6777
}
6778
#endif
6779

B
Blue Swirl 已提交
6780
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6781
{
P
pbrook 已提交
6782
    TCGv_i32 t0;
6783
    int l1, l2;
6784

6785 6786
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6787
    t0 = tcg_temp_local_new_i32();
6788 6789 6790 6791 6792 6793 6794
    /* 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);
6795
    gen_set_label(l2);
P
pbrook 已提交
6796
    tcg_temp_free_i32(t0);
6797 6798
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
6799
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6800
{
P
pbrook 已提交
6801
    TCGv_i32 t0;
6802 6803 6804 6805
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6806
    t0 = tcg_temp_local_new_i32();
6807 6808 6809 6810 6811 6812 6813
    /* 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);
6814
    gen_set_label(l2);
P
pbrook 已提交
6815
    tcg_temp_free_i32(t0);
6816 6817
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
6818
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6819
{
P
pbrook 已提交
6820
    TCGv_i32 t0;
6821 6822 6823 6824
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6825
    t0 = tcg_temp_local_new_i32();
6826 6827 6828 6829 6830 6831 6832
    /* 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);
6833
    gen_set_label(l2);
P
pbrook 已提交
6834
    tcg_temp_free_i32(t0);
6835 6836
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
B
Blue Swirl 已提交
6837
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6838
{
P
pbrook 已提交
6839
    TCGv_i32 t0 = tcg_temp_new_i32();
6840 6841
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
6842
    tcg_temp_free_i32(t0);
6843 6844
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
B
Blue Swirl 已提交
6845
static inline void gen_evmergehi(DisasContext *ctx)
6846 6847
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
6848
        gen_exception(ctx, POWERPC_EXCP_APU);
6849 6850 6851
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6852 6853
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864
    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 已提交
6865
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6866
{
6867 6868 6869
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
6870

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

7065
#if defined(TARGET_PPC64)
7066
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7067 7068 7069 7070 7071
#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 已提交
7072
static inline void gen_evsplatfi(DisasContext *ctx)
7073
{
7074
    uint64_t imm = rA(ctx->opcode) << 27;
7075

7076
#if defined(TARGET_PPC64)
7077
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7078 7079 7080 7081
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7082 7083
}

B
Blue Swirl 已提交
7084
static inline void gen_evsel(DisasContext *ctx)
7085 7086 7087 7088 7089
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7090
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7091
#if defined(TARGET_PPC64)
P
pbrook 已提交
7092 7093
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112
#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)
7113
    tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
7114 7115 7116 7117 7118 7119
#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)
7120
    tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
7121 7122 7123 7124
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7125
    tcg_temp_free_i32(t0);
7126 7127 7128 7129 7130 7131
#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 已提交
7132 7133

static void gen_evsel0(DisasContext *ctx)
7134 7135 7136
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7137 7138

static void gen_evsel1(DisasContext *ctx)
7139 7140 7141
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7142 7143

static void gen_evsel2(DisasContext *ctx)
7144 7145 7146
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7147 7148

static void gen_evsel3(DisasContext *ctx)
7149 7150 7151
{
    gen_evsel(ctx);
}
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 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309
/* 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);
}

7310 7311 7312 7313 7314 7315 7316 7317
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); //
7318
GEN_SPE(evmra,          speundef,      0x02, 0x13, 0x0000F800, PPC_SPE);
7319 7320 7321 7322
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); ////
7323 7324 7325
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);
7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339
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); ////

7340
/* SPE load and stores */
B
Blue Swirl 已提交
7341
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7342 7343 7344
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7345
    if (rA(ctx->opcode) == 0) {
7346
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7347
    } else {
7348
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
A
aurel32 已提交
7349 7350 7351 7352 7353 7354
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
7355
}
7356

B
Blue Swirl 已提交
7357
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7358 7359
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7360
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7361 7362
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7363
    gen_qemu_ld64(ctx, t0, addr);
7364 7365 7366 7367 7368
    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
7369
}
7370

B
Blue Swirl 已提交
7371
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7372
{
7373
#if defined(TARGET_PPC64)
7374
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7375
    gen_qemu_ld32u(ctx, t0, addr);
7376
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7377 7378
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7379 7380 7381
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7382 7383 7384
    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);
7385
#endif
7386
}
7387

B
Blue Swirl 已提交
7388
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7389 7390 7391
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7392
    gen_qemu_ld16u(ctx, t0, addr);
7393
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7394 7395
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7396 7397
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7398 7399
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7400 7401
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7402 7403
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7404
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7405
#else
A
aurel32 已提交
7406
    gen_qemu_ld16u(ctx, t0, addr);
7407
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7408 7409
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7410
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7411 7412
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7413
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7414 7415
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7416
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7417
#endif
7418
    tcg_temp_free(t0);
7419 7420
}

B
Blue Swirl 已提交
7421
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7422 7423
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7424
    gen_qemu_ld16u(ctx, t0, addr);
7425 7426 7427 7428 7429 7430 7431 7432 7433 7434
#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);
7435 7436
}

B
Blue Swirl 已提交
7437
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7438 7439
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7440
    gen_qemu_ld16u(ctx, t0, addr);
7441 7442 7443 7444 7445 7446 7447 7448
#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);
7449 7450
}

B
Blue Swirl 已提交
7451
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7452 7453
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7454
    gen_qemu_ld16s(ctx, t0, addr);
7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465
#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 已提交
7466
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7467 7468 7469
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7470
    gen_qemu_ld16u(ctx, t0, addr);
7471
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7472 7473
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7474 7475 7476
    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 已提交
7477
    gen_qemu_ld16u(ctx, t0, addr);
7478
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7479 7480
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7481 7482 7483 7484 7485
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7486
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7487 7488 7489
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7490 7491 7492
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7493 7494 7495 7496
    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 已提交
7497 7498 7499
    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);
7500 7501 7502
#endif
}

B
Blue Swirl 已提交
7503
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7504 7505 7506
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7507
    gen_qemu_ld16s(ctx, t0, addr);
7508
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7509 7510
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7511 7512 7513 7514
    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 已提交
7515 7516 7517
    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);
7518 7519 7520
#endif
}

B
Blue Swirl 已提交
7521
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7522 7523
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7524
    gen_qemu_ld32u(ctx, t0, addr);
7525
#if defined(TARGET_PPC64)
7526 7527 7528 7529 7530 7531 7532 7533 7534
    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 已提交
7535
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7536 7537 7538
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7539
    gen_qemu_ld16u(ctx, t0, addr);
7540 7541 7542
    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 已提交
7543 7544
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7545 7546 7547 7548
    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 已提交
7549
    gen_qemu_ld16u(ctx, t0, addr);
7550 7551
    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 已提交
7552 7553
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7554 7555
    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);
7556
#endif
7557 7558 7559
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7560
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7561 7562
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7563
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7564
#else
7565 7566
    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 已提交
7567
    gen_qemu_st64(ctx, t0, addr);
7568 7569 7570 7571
    tcg_temp_free_i64(t0);
#endif
}

B
Blue Swirl 已提交
7572
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7573
{
7574
#if defined(TARGET_PPC64)
7575 7576
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7577
    gen_qemu_st32(ctx, t0, addr);
7578 7579
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7580
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7581
#endif
A
aurel32 已提交
7582 7583
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7584 7585
}

B
Blue Swirl 已提交
7586
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7587 7588 7589 7590 7591 7592 7593
{
    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 已提交
7594 7595
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7596 7597
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7598
    gen_qemu_st16(ctx, t0, addr);
7599
#else
A
aurel32 已提交
7600
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7601
#endif
A
aurel32 已提交
7602
    gen_addr_add(ctx, addr, addr, 2);
7603
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7604
    gen_qemu_st16(ctx, t0, addr);
7605
    tcg_temp_free(t0);
A
aurel32 已提交
7606 7607
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7608 7609
}

B
Blue Swirl 已提交
7610
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7611 7612 7613 7614 7615 7616 7617
{
    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 已提交
7618 7619
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7620
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7621
    gen_qemu_st16(ctx, t0, addr);
7622 7623 7624
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7625
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7626 7627 7628 7629
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7630
    gen_qemu_st16(ctx, t0, addr);
7631 7632
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7633
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7634
#endif
A
aurel32 已提交
7635 7636
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7637 7638
}

B
Blue Swirl 已提交
7639
static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7640 7641 7642 7643
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7644
    gen_qemu_st32(ctx, t0, addr);
7645 7646
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7647
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7648 7649 7650
#endif
}

B
Blue Swirl 已提交
7651
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7652
{
A
aurel32 已提交
7653
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7654 7655 7656
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
B
Blue Swirl 已提交
7657
static void glue(gen_, name)(DisasContext *ctx)                                       \
7658 7659 7660
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7661
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7662 7663
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7664
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7665 7666
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
7667
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7668
    } else {                                                                  \
A
aurel32 已提交
7669
        gen_addr_reg_index(ctx, t0);                                          \
7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693
    }                                                                         \
    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);
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 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767

/* 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 已提交
7768 7769
#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
7770
static inline void gen_##name(DisasContext *ctx)                              \
7771
{                                                                             \
A
aurel32 已提交
7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783
    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);                                                        \
7784
}
A
aurel32 已提交
7785
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
7786
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800
{                                                                             \
    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 已提交
7801
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7802 7803 7804 7805 7806 7807 7808
{                                                                             \
    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 已提交
7809
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7810 7811 7812 7813
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
7814
static inline void gen_##name(DisasContext *ctx)                              \
7815
{                                                                             \
A
aurel32 已提交
7816 7817
    TCGv_i32 t0, t1;                                                          \
    TCGv_i64 t2;                                                              \
7818
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7819
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7820 7821
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834
    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);                                                        \
7835
}
A
aurel32 已提交
7836
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
7837
static inline void gen_##name(DisasContext *ctx)                              \
7838 7839
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7840
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7841 7842
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7843 7844
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],     \
                      cpu_gpr[rB(ctx->opcode)]);                              \
7845
}
A
aurel32 已提交
7846
#define GEN_SPEFPUOP_COMP_32(name)                                            \
B
Blue Swirl 已提交
7847
static inline void gen_##name(DisasContext *ctx)                              \
7848
{                                                                             \
A
aurel32 已提交
7849
    TCGv_i32 t0, t1;                                                          \
7850
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7851
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7852 7853
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7854 7855 7856 7857 7858 7859 7860 7861 7862
    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 已提交
7863
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7864 7865
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7866
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7867 7868 7869 7870 7871 7872 7873
        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 已提交
7874
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7875 7876
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7877
}
A
aurel32 已提交
7878
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
7879
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7880 7881 7882 7883 7884 7885 7886
{                                                                             \
    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 已提交
7887
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7888 7889 7890 7891 7892 7893 7894
{                                                                             \
    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 已提交
7895
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7896 7897 7898 7899 7900 7901 7902 7903
{                                                                             \
    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 已提交
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_gpr[rD(ctx->opcode)],                               \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_64_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 7930
        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 已提交
7931
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7932 7933
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7934
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7935 7936 7937 7938 7939 7940
        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 已提交
7941
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
7942 7943 7944
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7945
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956
        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
7957

7958 7959
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
7960 7961 7962 7963
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 已提交
7964
static inline void gen_evfsabs(DisasContext *ctx)
A
aurel32 已提交
7965 7966
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7967
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7968 7969 7970
        return;
    }
#if defined(TARGET_PPC64)
7971
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
A
aurel32 已提交
7972
#else
7973 7974
    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 已提交
7975 7976
#endif
}
B
Blue Swirl 已提交
7977
static inline void gen_evfsnabs(DisasContext *ctx)
A
aurel32 已提交
7978 7979
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7980
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7981 7982 7983
        return;
    }
#if defined(TARGET_PPC64)
7984
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
7985
#else
7986 7987
    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 已提交
7988 7989
#endif
}
B
Blue Swirl 已提交
7990
static inline void gen_evfsneg(DisasContext *ctx)
A
aurel32 已提交
7991 7992
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7993
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7994 7995 7996
        return;
    }
#if defined(TARGET_PPC64)
7997
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
7998
#else
7999 8000
    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 已提交
8001 8002 8003
#endif
}

8004
/* Conversion */
A
aurel32 已提交
8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015
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);

8016
/* Comparison */
A
aurel32 已提交
8017 8018 8019 8020 8021 8022
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);
8023 8024

/* Opcodes definitions */
8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038
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); //
8039 8040 8041

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8042 8043 8044 8045
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 已提交
8046
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
8047 8048
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8049
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8050 8051
        return;
    }
8052
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
A
aurel32 已提交
8053
}
B
Blue Swirl 已提交
8054
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
8055 8056
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8057
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8058 8059
        return;
    }
8060
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8061
}
B
Blue Swirl 已提交
8062
static inline void gen_efsneg(DisasContext *ctx)
A
aurel32 已提交
8063 8064
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8065
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8066 8067
        return;
    }
8068
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8069 8070
}

8071
/* Conversion */
A
aurel32 已提交
8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083
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);

8084
/* Comparison */
A
aurel32 已提交
8085 8086 8087 8088 8089 8090
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);
8091 8092

/* Opcodes definitions */
8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106
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); //
8107 8108 8109

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8110 8111 8112 8113
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 已提交
8114
static inline void gen_efdabs(DisasContext *ctx)
A
aurel32 已提交
8115 8116
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8117
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8118 8119 8120
        return;
    }
#if defined(TARGET_PPC64)
8121
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
A
aurel32 已提交
8122
#else
8123 8124
    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 已提交
8125 8126
#endif
}
B
Blue Swirl 已提交
8127
static inline void gen_efdnabs(DisasContext *ctx)
A
aurel32 已提交
8128 8129
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8130
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8131 8132 8133
        return;
    }
#if defined(TARGET_PPC64)
8134
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8135
#else
8136 8137
    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 已提交
8138 8139
#endif
}
B
Blue Swirl 已提交
8140
static inline void gen_efdneg(DisasContext *ctx)
A
aurel32 已提交
8141 8142
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
8143
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
8144 8145 8146
        return;
    }
#if defined(TARGET_PPC64)
8147
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8148
#else
8149 8150
    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 已提交
8151 8152 8153
#endif
}

8154
/* Conversion */
A
aurel32 已提交
8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169
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);
8170 8171

/* Comparison */
A
aurel32 已提交
8172 8173 8174 8175 8176 8177
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);
8178 8179

/* Opcodes definitions */
8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195
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); //
8196

A
Anthony Liguori 已提交
8197
static opcode_t opcodes[] = {
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 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270
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),
8271
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
8272 8273
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
8274
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
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
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),
8330 8331 8332
GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422
#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),
8423
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
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 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921
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),
8922
GEN_VXFORM_NOA(vexptefp, 5, 6),
8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960
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),
8961
GEN_SPE(evmra,          speundef,      0x02, 0x13, 0x0000F800, PPC_SPE),
8962 8963 8964 8965
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),
8966 8967 8968
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),
8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053
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),
};

9054
#include "translate_init.c"
9055
#include "helper_regs.h"
B
bellard 已提交
9056

9057
/*****************************************************************************/
9058
/* Misc PowerPC helpers */
9059
void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
9060
                     int flags)
B
bellard 已提交
9061
{
9062 9063 9064
#define RGPL  4
#define RFPL  4

B
bellard 已提交
9065 9066
    int i;

9067
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
9068 9069
                TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
                env->nip, env->lr, env->ctr, env->xer);
9070 9071 9072
    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);
9073
#if !defined(NO_TIMER_DUMP)
9074
    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
9075
#if !defined(CONFIG_USER_ONLY)
9076
                " DECR %08" PRIu32
9077 9078
#endif
                "\n",
J
j_mayer 已提交
9079
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
9080 9081 9082 9083
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
9084
#endif
9085
    for (i = 0; i < 32; i++) {
9086 9087
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
9088
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
9089
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
9090
            cpu_fprintf(f, "\n");
9091
    }
9092
    cpu_fprintf(f, "CR ");
9093
    for (i = 0; i < 8; i++)
B
bellard 已提交
9094 9095
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
9096 9097 9098 9099 9100 9101 9102 9103
    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 已提交
9104
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
9105
    }
9106 9107
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
9108 9109 9110
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
9111
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
9112
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
9113
            cpu_fprintf(f, "\n");
B
bellard 已提交
9114
    }
9115
    cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
9116
#if !defined(CONFIG_USER_ONLY)
9117 9118 9119
    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);
9120
#endif
B
bellard 已提交
9121

9122 9123
#undef RGPL
#undef RFPL
B
bellard 已提交
9124 9125
}

9126
void cpu_dump_statistics (CPUState *env, FILE*f, fprintf_function cpu_fprintf,
9127 9128 9129
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
A
Anthony Liguori 已提交
9130
    opc_handler_t **t1, **t2, **t3, *handler;
9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146
    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 已提交
9147
                                    "%016" PRIx64 " %" PRId64 "\n",
9148 9149 9150 9151 9152 9153 9154 9155
                                    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 已提交
9156
                                "%016" PRIx64 " %" PRId64 "\n",
9157 9158 9159 9160 9161 9162 9163
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
B
Blue Swirl 已提交
9164 9165
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
                        " %" PRId64 "\n",
9166 9167 9168 9169 9170 9171 9172
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

9173
/*****************************************************************************/
B
Blue Swirl 已提交
9174 9175 9176
static inline void gen_intermediate_code_internal(CPUState *env,
                                                  TranslationBlock *tb,
                                                  int search_pc)
B
bellard 已提交
9177
{
9178
    DisasContext ctx, *ctxp = &ctx;
A
Anthony Liguori 已提交
9179
    opc_handler_t **table, *handler;
B
bellard 已提交
9180
    target_ulong pc_start;
B
bellard 已提交
9181
    uint16_t *gen_opc_end;
9182
    CPUBreakpoint *bp;
B
bellard 已提交
9183
    int j, lj = -1;
P
pbrook 已提交
9184 9185
    int num_insns;
    int max_insns;
B
bellard 已提交
9186 9187 9188

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
9189
    ctx.nip = pc_start;
B
bellard 已提交
9190
    ctx.tb = tb;
9191
    ctx.exception = POWERPC_EXCP_NONE;
9192
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
9193 9194 9195
    ctx.mem_idx = env->mmu_idx;
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
9196 9197
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
9198
#endif
B
bellard 已提交
9199
    ctx.fpu_enabled = msr_fp;
9200
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
9201 9202 9203
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
9204 9205 9206 9207
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
9208
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
9209
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
9210
    else
9211
        ctx.singlestep_enabled = 0;
9212
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
9213 9214 9215
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
9216
#if defined (DO_SINGLE_STEP) && 0
9217 9218 9219
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
9220 9221 9222 9223 9224 9225
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

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

9350
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
9351
{
9352
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
9353 9354
}

9355
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
9356
{
9357
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
9358
}
A
aurel32 已提交
9359 9360 9361 9362 9363 9364

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