translate.c 360.9 KB
Newer Older
B
bellard 已提交
1
/*
2
 *  PowerPC emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
S
Scott Wood 已提交
5
 *  Copyright (C) 2011 Freescale Semiconductor, Inc.
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
B
bellard 已提交
19
 */
B
bellard 已提交
20

B
bellard 已提交
21
#include "cpu.h"
22
#include "disas/disas.h"
B
bellard 已提交
23
#include "tcg-op.h"
24
#include "qemu/host-utils.h"
B
bellard 已提交
25

P
pbrook 已提交
26 27 28 29
#include "helper.h"
#define GEN_HELPER 1
#include "helper.h"

30 31 32 33
#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2
#define GDBSTUB_SINGLE_STEP 0x4

34
/* Include definitions for instructions classes and implementations flags */
35
//#define PPC_DEBUG_DISAS
36
//#define DO_PPC_STATISTICS
B
bellard 已提交
37

38
#ifdef PPC_DEBUG_DISAS
39
#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
40 41 42
#else
#  define LOG_DISAS(...) do { } while (0)
#endif
43 44
/*****************************************************************************/
/* Code translation helpers                                                  */
B
bellard 已提交
45

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

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

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

P
pbrook 已提交
83 84
    if (done_init)
        return;
A
aurel32 已提交
85

P
pbrook 已提交
86 87
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");

A
aurel32 已提交
88
    p = cpu_reg_names;
89
    cpu_reg_names_size = sizeof(cpu_reg_names);
A
aurel32 已提交
90 91

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

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

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

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

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

P
pbrook 已提交
142
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
143
                                 offsetof(CPUPPCState, nip), "nip");
A
aurel32 已提交
144

145
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
146
                                 offsetof(CPUPPCState, msr), "msr");
147

P
pbrook 已提交
148
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
149
                                 offsetof(CPUPPCState, ctr), "ctr");
A
aurel32 已提交
150

P
pbrook 已提交
151
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
152
                                offsetof(CPUPPCState, lr), "lr");
A
aurel32 已提交
153

D
David Gibson 已提交
154 155
#if defined(TARGET_PPC64)
    cpu_cfar = tcg_global_mem_new(TCG_AREG0,
156
                                  offsetof(CPUPPCState, cfar), "cfar");
D
David Gibson 已提交
157 158
#endif

P
pbrook 已提交
159
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
160
                                 offsetof(CPUPPCState, xer), "xer");
A
aurel32 已提交
161

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

166 167
    cpu_fpscr = tcg_global_mem_new(TCG_AREG0,
                                   offsetof(CPUPPCState, fpscr), "fpscr");
168

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

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

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

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

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

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

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

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

244
    tcg_temp_free_i32(t0);
245 246
}

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

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

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

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

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

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

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

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

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

B
bellard 已提交
322
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
323 324 325 326
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)

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

328
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
329 330 331 332
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)

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

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

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

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

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

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

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

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

B
Blue Swirl 已提交
428
static inline uint32_t BD(uint32_t opcode)
B
bellard 已提交
429 430 431 432 433 434 435 436 437 438 439 440
{
    return (opcode >> 0) & 0xFFFC;
}

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

/* Create a mask between <start> and <end> bits */
B
Blue Swirl 已提交
441
static inline target_ulong MASK(uint32_t start, uint32_t end)
B
bellard 已提交
442
{
443
    target_ulong ret;
B
bellard 已提交
444

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

    return ret;
}

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

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

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

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

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

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

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

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

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

    l1 = gen_new_label();
    l2 = gen_new_label();
    l3 = gen_new_label();
    if (s) {
603 604
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
605
    } else {
606 607
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
608 609 610 611 612 613 614 615 616 617 618
    }
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
    tcg_gen_br(l3);
    gen_set_label(l1);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
    tcg_gen_br(l3);
    gen_set_label(l2);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
    gen_set_label(l3);
}

B
Blue Swirl 已提交
619
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
620
{
621 622 623
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
624 625 626
}

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

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

B
Blue Swirl 已提交
652
static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
653 654 655 656 657 658 659 660 661 662
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode))
        gen_op_cmpi32(reg, 0, 1, 0);
    else
#endif
        gen_op_cmpi(reg, 0, 1, 0);
}

/* cmp */
B
Blue Swirl 已提交
663
static void gen_cmp(DisasContext *ctx)
664 665 666 667 668 669 670 671 672 673 674 675
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     1, crfD(ctx->opcode));
    else
#endif
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   1, crfD(ctx->opcode));
}

/* cmpi */
B
Blue Swirl 已提交
676
static void gen_cmpi(DisasContext *ctx)
677 678 679 680 681 682 683 684 685 686 687 688
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                      1, crfD(ctx->opcode));
    else
#endif
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                    1, crfD(ctx->opcode));
}

/* cmpl */
B
Blue Swirl 已提交
689
static void gen_cmpl(DisasContext *ctx)
690 691 692 693 694 695 696 697 698 699 700 701
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     0, crfD(ctx->opcode));
    else
#endif
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   0, crfD(ctx->opcode));
}

/* cmpli */
B
Blue Swirl 已提交
702
static void gen_cmpli(DisasContext *ctx)
703 704 705 706 707 708 709 710 711 712 713 714
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                      0, crfD(ctx->opcode));
    else
#endif
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                    0, crfD(ctx->opcode));
}

/* isel (PowerPC 2.03 specification) */
B
Blue Swirl 已提交
715
static void gen_isel(DisasContext *ctx)
716 717 718 719
{
    int l1, l2;
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;
P
pbrook 已提交
720
    TCGv_i32 t0;
721 722 723 724 725

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

    mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
726
    t0 = tcg_temp_new_i32();
727 728
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
729 730 731 732 733 734 735 736
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    else
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    gen_set_label(l2);
P
pbrook 已提交
737
    tcg_temp_free_i32(t0);
738 739
}

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

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

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

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

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

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

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

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

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

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

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
    tcg_gen_add_tl(t0, arg1, arg2);

    if (compute_ca) {
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
    }
    if (add_ca) {
        tcg_gen_add_tl(t0, t0, t1);
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
        tcg_temp_free(t1);
    }
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
    }

    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, t0);

P
pbrook 已提交
860
    if (!TCGV_EQUAL(t0, ret)) {
861 862 863
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
864
}
865 866
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
B
Blue Swirl 已提交
867
static void glue(gen_, name)(DisasContext *ctx)                                       \
868 869 870 871 872 873 874 875
{                                                                             \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
                     add_ca, compute_ca, compute_ov);                         \
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
                                add_ca, compute_ca, compute_ov)               \
B
Blue Swirl 已提交
876
static void glue(gen_, name)(DisasContext *ctx)                                       \
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
{                                                                             \
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
                     add_ca, compute_ca, compute_ov);                         \
    tcg_temp_free(t0);                                                        \
}

/* add  add.  addo  addo. */
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
/* addc  addc.  addco  addco. */
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
/* adde  adde.  addeo  addeo. */
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
/* addme  addme.  addmeo  addmeo.  */
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
/* addze  addze.  addzeo  addzeo.*/
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
/* addi */
B
Blue Swirl 已提交
901
static void gen_addi(DisasContext *ctx)
902
{
903 904 905 906 907 908 909 910
    target_long simm = SIMM(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        /* li case */
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
    } else {
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
    }
911
}
912
/* addic  addic.*/
B
Blue Swirl 已提交
913 914
static inline void gen_op_addic(DisasContext *ctx, TCGv ret, TCGv arg1,
                                int compute_Rc0)
915
{
916 917 918 919 920 921
    target_long simm = SIMM(ctx->opcode);

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

    if (likely(simm != 0)) {
P
pbrook 已提交
922
        TCGv t0 = tcg_temp_local_new();
923 924 925 926 927 928 929 930 931 932
        tcg_gen_addi_tl(t0, arg1, simm);
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    } else {
        tcg_gen_mov_tl(ret, arg1);
    }
    if (compute_Rc0) {
        gen_set_Rc0(ctx, ret);
    }
933
}
B
Blue Swirl 已提交
934 935

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

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

945
/* addis */
B
Blue Swirl 已提交
946
static void gen_addis(DisasContext *ctx)
947
{
948 949 950 951 952 953 954 955
    target_long simm = SIMM(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        /* lis case */
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
    } else {
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
    }
956
}
957

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

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

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

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

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

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

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

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

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

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

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

1176
/* mulld  mulld. */
B
Blue Swirl 已提交
1177
static void gen_mulld(DisasContext *ctx)
1178
{
1179 1180 1181 1182
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1183
}
1184

1185
/* mulldo  mulldo. */
1186 1187 1188 1189 1190 1191 1192 1193
static void gen_mulldo(DisasContext *ctx)
{
    gen_helper_mulldo(cpu_gpr[rD(ctx->opcode)], cpu_env,
                      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)]);
    }
}
1194
#endif
1195 1196

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1541
/* popcntb : PowerPC 2.03 specification */
B
Blue Swirl 已提交
1542
static void gen_popcntb(DisasContext *ctx)
1543
{
1544 1545 1546 1547 1548 1549 1550 1551
    gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
}

static void gen_popcntw(DisasContext *ctx)
{
    gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
}

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

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

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

B
bellard 已提交
1573
/***                             Integer rotate                            ***/
B
Blue Swirl 已提交
1574

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

B
bellard 已提交
1850
/***                             Integer shift                             ***/
B
Blue Swirl 已提交
1851

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2049 2050 2051
#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);
2052

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

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

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

2117
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
B
Blue Swirl 已提交
2118
static void gen_f##name(DisasContext *ctx)                                    \
2119
{                                                                             \
2120
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2121
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2122 2123
        return;                                                               \
    }                                                                         \
2124 2125
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2126
    gen_reset_fpstatus();                                                     \
2127 2128
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
                       cpu_fpr[rB(ctx->opcode)]);                             \
A
aurel32 已提交
2129 2130
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2131 2132
}

2133
/* fadd - fadds */
2134
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2135
/* fdiv - fdivs */
2136
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2137
/* fmul - fmuls */
2138
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2139

2140
/* fre */
2141
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2142

2143
/* fres */
2144
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2145

2146
/* frsqrte */
2147 2148 2149
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

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

2166
/* fsel */
2167
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2168
/* fsub - fsubs */
2169
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2170
/* Optional: */
B
Blue Swirl 已提交
2171

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

B
Blue Swirl 已提交
2187
static void gen_fsqrts(DisasContext *ctx)
B
bellard 已提交
2188
{
2189
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2190
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2191 2192
        return;
    }
2193 2194
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2195
    gen_reset_fpstatus();
2196 2197 2198 2199
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
                     cpu_fpr[rB(ctx->opcode)]);
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
                    cpu_fpr[rD(ctx->opcode)]);
A
aurel32 已提交
2200
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
B
bellard 已提交
2201 2202 2203
}

/***                     Floating-Point multiply-and-add                   ***/
2204
/* fmadd - fmadds */
2205
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2206
/* fmsub - fmsubs */
2207
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2208
/* fnmadd - fnmadds */
2209
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2210
/* fnmsub - fnmsubs */
2211
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2212 2213 2214

/***                     Floating-Point round & convert                    ***/
/* fctiw */
2215
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2216
/* fctiwz */
2217
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2218
/* frsp */
2219
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
2220 2221
#if defined(TARGET_PPC64)
/* fcfid */
2222
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
2223
/* fctid */
2224
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2225
/* fctidz */
2226
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2227
#endif
B
bellard 已提交
2228

2229
/* frin */
2230
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2231
/* friz */
2232
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2233
/* frip */
2234
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2235
/* frim */
2236
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2237

B
bellard 已提交
2238
/***                         Floating-Point compare                        ***/
B
Blue Swirl 已提交
2239

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

/* fcmpu */
B
Blue Swirl 已提交
2259
static void gen_fcmpu(DisasContext *ctx)
B
bellard 已提交
2260
{
A
aurel32 已提交
2261
    TCGv_i32 crf;
2262
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2263
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2264 2265
        return;
    }
2266 2267
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2268
    gen_reset_fpstatus();
A
aurel32 已提交
2269
    crf = tcg_const_i32(crfD(ctx->opcode));
2270 2271
    gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
                     cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2272
    tcg_temp_free_i32(crf);
2273
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2274 2275
}

2276 2277
/***                         Floating-point move                           ***/
/* fabs */
2278 2279
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2280 2281

/* fmr  - fmr. */
2282
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
B
Blue Swirl 已提交
2283
static void gen_fmr(DisasContext *ctx)
2284
{
2285
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2286
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2287 2288
        return;
    }
A
aurel32 已提交
2289 2290
    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);
2291 2292 2293
}

/* fnabs */
2294 2295
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2296
/* fneg */
2297 2298
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2299

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

2302
/* mcrfs */
B
Blue Swirl 已提交
2303
static void gen_mcrfs(DisasContext *ctx)
B
bellard 已提交
2304
{
2305
    TCGv tmp = tcg_temp_new();
2306 2307
    int bfa;

2308
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2309
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2310 2311
        return;
    }
2312
    bfa = 4 * (7 - crfS(ctx->opcode));
2313 2314 2315
    tcg_gen_shri_tl(tmp, cpu_fpscr, bfa);
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
    tcg_temp_free(tmp);
2316
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2317
    tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
B
bellard 已提交
2318 2319 2320
}

/* mffs */
B
Blue Swirl 已提交
2321
static void gen_mffs(DisasContext *ctx)
B
bellard 已提交
2322
{
2323
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2324
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2325 2326
        return;
    }
2327
    gen_reset_fpstatus();
2328
    tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
A
aurel32 已提交
2329
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2330 2331 2332
}

/* mtfsb0 */
B
Blue Swirl 已提交
2333
static void gen_mtfsb0(DisasContext *ctx)
B
bellard 已提交
2334
{
B
bellard 已提交
2335
    uint8_t crb;
2336

2337
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2338
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2339 2340
        return;
    }
A
aurel32 已提交
2341
    crb = 31 - crbD(ctx->opcode);
2342
    gen_reset_fpstatus();
A
aurel32 已提交
2343
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2344 2345 2346 2347
        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);
2348
        gen_helper_fpscr_clrbit(cpu_env, t0);
A
aurel32 已提交
2349 2350
        tcg_temp_free_i32(t0);
    }
2351
    if (unlikely(Rc(ctx->opcode) != 0)) {
2352 2353
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2354
    }
B
bellard 已提交
2355 2356 2357
}

/* mtfsb1 */
B
Blue Swirl 已提交
2358
static void gen_mtfsb1(DisasContext *ctx)
B
bellard 已提交
2359
{
B
bellard 已提交
2360
    uint8_t crb;
2361

2362
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2363
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2364 2365
        return;
    }
A
aurel32 已提交
2366
    crb = 31 - crbD(ctx->opcode);
2367 2368
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
A
aurel32 已提交
2369
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2370 2371 2372 2373
        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);
2374
        gen_helper_fpscr_setbit(cpu_env, t0);
2375
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2376
    }
2377
    if (unlikely(Rc(ctx->opcode) != 0)) {
2378 2379
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2380 2381
    }
    /* We can raise a differed exception */
2382
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2383 2384 2385
}

/* mtfsf */
B
Blue Swirl 已提交
2386
static void gen_mtfsf(DisasContext *ctx)
B
bellard 已提交
2387
{
2388
    TCGv_i32 t0;
B
blueswir1 已提交
2389
    int L = ctx->opcode & 0x02000000;
A
aurel32 已提交
2390

2391
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2392
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2393 2394
        return;
    }
2395 2396
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2397
    gen_reset_fpstatus();
B
blueswir1 已提交
2398 2399 2400 2401
    if (L)
        t0 = tcg_const_i32(0xff);
    else
        t0 = tcg_const_i32(FM(ctx->opcode));
2402
    gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
2403
    tcg_temp_free_i32(t0);
2404
    if (unlikely(Rc(ctx->opcode) != 0)) {
2405 2406
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2407 2408
    }
    /* We can raise a differed exception */
2409
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2410 2411 2412
}

/* mtfsfi */
B
Blue Swirl 已提交
2413
static void gen_mtfsfi(DisasContext *ctx)
B
bellard 已提交
2414
{
2415
    int bf, sh;
2416 2417
    TCGv_i64 t0;
    TCGv_i32 t1;
2418

2419
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2420
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2421 2422
        return;
    }
2423 2424
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
2425 2426
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2427
    gen_reset_fpstatus();
2428
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
A
aurel32 已提交
2429
    t1 = tcg_const_i32(1 << sh);
2430
    gen_helper_store_fpscr(cpu_env, t0, t1);
2431 2432
    tcg_temp_free_i64(t0);
    tcg_temp_free_i32(t1);
2433
    if (unlikely(Rc(ctx->opcode) != 0)) {
2434 2435
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2436 2437
    }
    /* We can raise a differed exception */
2438
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2439 2440
}

2441 2442
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
B
Blue Swirl 已提交
2443 2444
static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
                                      target_long maskl)
2445 2446 2447
{
    target_long simm = SIMM(ctx->opcode);

2448
    simm &= ~maskl;
A
aurel32 已提交
2449 2450 2451 2452 2453 2454
    if (rA(ctx->opcode) == 0) {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_movi_tl(EA, (uint32_t)simm);
        } else
#endif
2455
        tcg_gen_movi_tl(EA, simm);
A
aurel32 已提交
2456
    } else if (likely(simm != 0)) {
2457
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
A
aurel32 已提交
2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468
#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
2469
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2470
    }
2471 2472
}

B
Blue Swirl 已提交
2473
static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2474
{
A
aurel32 已提交
2475 2476 2477 2478 2479 2480
    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
2481
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2482
    } else {
2483
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2484 2485 2486 2487 2488 2489
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
2490 2491
}

B
Blue Swirl 已提交
2492
static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2493
{
A
aurel32 已提交
2494
    if (rA(ctx->opcode) == 0) {
2495
        tcg_gen_movi_tl(EA, 0);
A
aurel32 已提交
2496 2497 2498 2499 2500 2501 2502 2503 2504 2505
    } 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 已提交
2506 2507
static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                target_long val)
A
aurel32 已提交
2508 2509 2510 2511 2512 2513 2514
{
    tcg_gen_addi_tl(ret, arg1, val);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode) {
        tcg_gen_ext32u_tl(ret, ret);
    }
#endif
2515 2516
}

B
Blue Swirl 已提交
2517
static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2518 2519 2520 2521 2522 2523 2524 2525 2526 2527
{
    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);
2528
    gen_helper_raise_exception_err(cpu_env, t1, t2);
2529 2530 2531 2532 2533 2534
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    gen_set_label(l1);
    tcg_temp_free(t0);
}

2535
/***                             Integer load                              ***/
B
Blue Swirl 已提交
2536
static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2537 2538 2539 2540
{
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2541
static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2542 2543 2544 2545
{
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
}

B
Blue Swirl 已提交
2546
static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2547 2548 2549
{
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2550
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2551
    }
A
aurel32 已提交
2552 2553
}

B
Blue Swirl 已提交
2554
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2555
{
A
aurel32 已提交
2556 2557
    if (unlikely(ctx->le_mode)) {
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2558
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2559 2560 2561 2562
        tcg_gen_ext16s_tl(arg1, arg1);
    } else {
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2563 2564
}

B
Blue Swirl 已提交
2565
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2566
{
A
aurel32 已提交
2567 2568
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2569
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2570
    }
A
aurel32 已提交
2571 2572
}

A
aurel32 已提交
2573
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
2574
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2575
{
B
blueswir1 已提交
2576
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2577
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2578 2579
        tcg_gen_bswap32_tl(arg1, arg1);
        tcg_gen_ext32s_tl(arg1, arg1);
A
aurel32 已提交
2580
    } else
A
aurel32 已提交
2581
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2582
}
A
aurel32 已提交
2583
#endif
A
aurel32 已提交
2584

B
Blue Swirl 已提交
2585
static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2586
{
A
aurel32 已提交
2587 2588
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2589
        tcg_gen_bswap64_i64(arg1, arg1);
A
aurel32 已提交
2590
    }
A
aurel32 已提交
2591 2592
}

B
Blue Swirl 已提交
2593
static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2594
{
A
aurel32 已提交
2595
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2596 2597
}

B
Blue Swirl 已提交
2598
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2599
{
A
aurel32 已提交
2600 2601 2602
    if (unlikely(ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2603
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2604 2605 2606 2607 2608
        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 已提交
2609 2610
}

B
Blue Swirl 已提交
2611
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2612
{
A
aurel32 已提交
2613
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2614 2615 2616
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2617 2618 2619 2620 2621
        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 已提交
2622 2623
}

B
Blue Swirl 已提交
2624
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2625
{
A
aurel32 已提交
2626
    if (unlikely(ctx->le_mode)) {
P
pbrook 已提交
2627
        TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
2628
        tcg_gen_bswap64_i64(t0, arg1);
A
aurel32 已提交
2629
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
P
pbrook 已提交
2630
        tcg_temp_free_i64(t0);
A
aurel32 已提交
2631
    } else
A
aurel32 已提交
2632
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2633 2634
}

2635
#define GEN_LD(name, ldop, opc, type)                                         \
B
Blue Swirl 已提交
2636
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2637
{                                                                             \
A
aurel32 已提交
2638 2639 2640 2641 2642
    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 已提交
2643
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2644 2645
}

2646
#define GEN_LDU(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
2647
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2648
{                                                                             \
A
aurel32 已提交
2649
    TCGv EA;                                                                  \
2650 2651
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2652
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2653
        return;                                                               \
2654
    }                                                                         \
A
aurel32 已提交
2655
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2656
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2657
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2658
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2659
    else                                                                      \
A
aurel32 已提交
2660 2661
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2662 2663
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2664 2665
}

2666
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2667
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2668
{                                                                             \
A
aurel32 已提交
2669
    TCGv EA;                                                                  \
2670 2671
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2672
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2673
        return;                                                               \
2674
    }                                                                         \
A
aurel32 已提交
2675
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2676
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2677 2678
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2679 2680
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2681 2682
}

2683
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
B
Blue Swirl 已提交
2684
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2685
{                                                                             \
A
aurel32 已提交
2686 2687 2688 2689 2690
    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 已提交
2691
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2692
}
2693 2694
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2695

2696 2697 2698 2699 2700
#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 已提交
2701 2702

/* lbz lbzu lbzux lbzx */
2703
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2704
/* lha lhau lhaux lhax */
2705
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2706
/* lhz lhzu lhzux lhzx */
2707
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2708
/* lwz lwzu lwzux lwzx */
2709
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2710 2711
#if defined(TARGET_PPC64)
/* lwaux */
2712
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2713
/* lwax */
2714
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2715
/* ldux */
2716
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2717
/* ldx */
2718
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
B
Blue Swirl 已提交
2719 2720

static void gen_ld(DisasContext *ctx)
2721
{
A
aurel32 已提交
2722
    TCGv EA;
2723 2724 2725
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
A
aurel32 已提交
2726
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2727 2728 2729
            return;
        }
    }
A
aurel32 已提交
2730
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2731
    EA = tcg_temp_new();
A
aurel32 已提交
2732
    gen_addr_imm_index(ctx, EA, 0x03);
2733 2734
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2735
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2736 2737
    } else {
        /* ld - ldu */
A
aurel32 已提交
2738
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2739 2740
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2741 2742
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2743
}
B
Blue Swirl 已提交
2744

2745
/* lq */
B
Blue Swirl 已提交
2746
static void gen_lq(DisasContext *ctx)
2747 2748
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2749
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2750 2751
#else
    int ra, rd;
A
aurel32 已提交
2752
    TCGv EA;
2753 2754

    /* Restore CPU state */
A
aurel32 已提交
2755
    if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2756
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2757 2758 2759 2760 2761
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
A
aurel32 已提交
2762
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2763 2764
        return;
    }
A
aurel32 已提交
2765
    if (unlikely(ctx->le_mode)) {
2766
        /* Little-endian mode is not handled */
A
aurel32 已提交
2767
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2768 2769
        return;
    }
A
aurel32 已提交
2770
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2771
    EA = tcg_temp_new();
A
aurel32 已提交
2772 2773 2774 2775
    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 已提交
2776
    tcg_temp_free(EA);
2777 2778
#endif
}
2779
#endif
B
bellard 已提交
2780 2781

/***                              Integer store                            ***/
2782
#define GEN_ST(name, stop, opc, type)                                         \
B
Blue Swirl 已提交
2783
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2784
{                                                                             \
A
aurel32 已提交
2785 2786 2787 2788 2789
    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 已提交
2790
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2791 2792
}

2793
#define GEN_STU(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
2794
static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2795
{                                                                             \
A
aurel32 已提交
2796
    TCGv EA;                                                                  \
2797
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2798
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2799
        return;                                                               \
2800
    }                                                                         \
A
aurel32 已提交
2801
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2802
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2803
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2804
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2805
    else                                                                      \
A
aurel32 已提交
2806 2807
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2808 2809
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2810 2811
}

2812
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2813
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2814
{                                                                             \
A
aurel32 已提交
2815
    TCGv EA;                                                                  \
2816
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2817
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2818
        return;                                                               \
2819
    }                                                                         \
A
aurel32 已提交
2820
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2821
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2822 2823
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2824 2825
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2826 2827
}

2828 2829
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2830
{                                                                             \
A
aurel32 已提交
2831 2832 2833 2834 2835
    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 已提交
2836
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2837
}
2838 2839
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2840

2841 2842 2843 2844 2845
#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 已提交
2846 2847

/* stb stbu stbux stbx */
2848
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
B
bellard 已提交
2849
/* sth sthu sthux sthx */
2850
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2851
/* stw stwu stwux stwx */
2852
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2853
#if defined(TARGET_PPC64)
2854 2855
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
B
Blue Swirl 已提交
2856 2857

static void gen_std(DisasContext *ctx)
2858
{
2859
    int rs;
A
aurel32 已提交
2860
    TCGv EA;
2861 2862 2863 2864

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2865
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2866 2867
#else
        /* stq */
A
aurel32 已提交
2868
        if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2869
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2870 2871 2872
            return;
        }
        if (unlikely(rs & 1)) {
A
aurel32 已提交
2873
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2874 2875
            return;
        }
A
aurel32 已提交
2876
        if (unlikely(ctx->le_mode)) {
2877
            /* Little-endian mode is not handled */
A
aurel32 已提交
2878
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2879 2880
            return;
        }
A
aurel32 已提交
2881
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2882
        EA = tcg_temp_new();
A
aurel32 已提交
2883 2884 2885 2886
        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 已提交
2887
        tcg_temp_free(EA);
2888 2889 2890 2891 2892
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
A
aurel32 已提交
2893
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2894 2895 2896
                return;
            }
        }
A
aurel32 已提交
2897
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2898
        EA = tcg_temp_new();
A
aurel32 已提交
2899 2900
        gen_addr_imm_index(ctx, EA, 0x03);
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2901
        if (Rc(ctx->opcode))
A
aurel32 已提交
2902 2903
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
2904 2905 2906
    }
}
#endif
B
bellard 已提交
2907 2908
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
2909
static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2910
{
A
aurel32 已提交
2911 2912
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2913
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2914
    }
A
aurel32 已提交
2915
}
2916
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
A
aurel32 已提交
2917

B
bellard 已提交
2918
/* lwbrx */
2919
static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2920
{
A
aurel32 已提交
2921 2922
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2923
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2924
    }
A
aurel32 已提交
2925
}
2926
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
A
aurel32 已提交
2927

2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939
#if defined(TARGET_PPC64)
/* ldbrx */
static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
        tcg_gen_bswap64_tl(arg1, arg1);
    }
}
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
#endif  /* TARGET_PPC64 */

B
bellard 已提交
2940
/* sthbrx */
2941
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2942
{
A
aurel32 已提交
2943 2944 2945
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2946
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2947 2948 2949 2950 2951
        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 已提交
2952
}
2953
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
A
aurel32 已提交
2954

B
bellard 已提交
2955
/* stwbrx */
2956
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2957
{
A
aurel32 已提交
2958
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2959 2960 2961
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2962 2963 2964 2965 2966
        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 已提交
2967
}
2968
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2969

2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985
#if defined(TARGET_PPC64)
/* stdbrx */
static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_bswap64_tl(t0, arg1);
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
    }
}
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
#endif  /* TARGET_PPC64 */

B
bellard 已提交
2986
/***                    Integer load and store multiple                    ***/
B
Blue Swirl 已提交
2987

2988
/* lmw */
B
Blue Swirl 已提交
2989
static void gen_lmw(DisasContext *ctx)
B
bellard 已提交
2990
{
A
aurel32 已提交
2991 2992 2993
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2994
    /* NIP cannot be restored if the memory exception comes from an helper */
2995
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2996 2997 2998
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rD(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2999
    gen_helper_lmw(cpu_env, t0, t1);
3000 3001
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3002 3003 3004
}

/* stmw */
B
Blue Swirl 已提交
3005
static void gen_stmw(DisasContext *ctx)
B
bellard 已提交
3006
{
A
aurel32 已提交
3007 3008 3009
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
3010
    /* NIP cannot be restored if the memory exception comes from an helper */
3011
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3012 3013 3014
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rS(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
3015
    gen_helper_stmw(cpu_env, t0, t1);
3016 3017
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3018 3019 3020
}

/***                    Integer load and store strings                     ***/
3021

B
bellard 已提交
3022
/* lswi */
3023
/* PowerPC32 specification says we must generate an exception if
3024 3025 3026 3027
 * 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 已提交
3028
static void gen_lswi(DisasContext *ctx)
B
bellard 已提交
3029
{
3030 3031
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3032 3033
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
3034
    int ra = rA(ctx->opcode);
B
bellard 已提交
3035 3036 3037 3038 3039
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
3040 3041 3042
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
A
aurel32 已提交
3043
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3044
        return;
B
bellard 已提交
3045
    }
A
aurel32 已提交
3046
    gen_set_access_type(ctx, ACCESS_INT);
3047
    /* NIP cannot be restored if the memory exception comes from an helper */
3048
    gen_update_nip(ctx, ctx->nip - 4);
3049
    t0 = tcg_temp_new();
A
aurel32 已提交
3050
    gen_addr_register(ctx, t0);
3051 3052
    t1 = tcg_const_i32(nb);
    t2 = tcg_const_i32(start);
3053
    gen_helper_lsw(cpu_env, t0, t1, t2);
3054 3055 3056
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3057 3058 3059
}

/* lswx */
B
Blue Swirl 已提交
3060
static void gen_lswx(DisasContext *ctx)
B
bellard 已提交
3061
{
A
aurel32 已提交
3062 3063 3064
    TCGv t0;
    TCGv_i32 t1, t2, t3;
    gen_set_access_type(ctx, ACCESS_INT);
3065
    /* NIP cannot be restored if the memory exception comes from an helper */
3066
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3067 3068 3069 3070 3071
    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));
3072
    gen_helper_lswx(cpu_env, t0, t1, t2, t3);
3073 3074 3075 3076
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
B
bellard 已提交
3077 3078 3079
}

/* stswi */
B
Blue Swirl 已提交
3080
static void gen_stswi(DisasContext *ctx)
B
bellard 已提交
3081
{
A
aurel32 已提交
3082 3083
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3084
    int nb = NB(ctx->opcode);
A
aurel32 已提交
3085
    gen_set_access_type(ctx, ACCESS_INT);
3086
    /* NIP cannot be restored if the memory exception comes from an helper */
3087
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3088 3089
    t0 = tcg_temp_new();
    gen_addr_register(ctx, t0);
B
bellard 已提交
3090 3091
    if (nb == 0)
        nb = 32;
3092
    t1 = tcg_const_i32(nb);
A
aurel32 已提交
3093
    t2 = tcg_const_i32(rS(ctx->opcode));
3094
    gen_helper_stsw(cpu_env, t0, t1, t2);
3095 3096 3097
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3098 3099 3100
}

/* stswx */
B
Blue Swirl 已提交
3101
static void gen_stswx(DisasContext *ctx)
B
bellard 已提交
3102
{
A
aurel32 已提交
3103 3104 3105
    TCGv t0;
    TCGv_i32 t1, t2;
    gen_set_access_type(ctx, ACCESS_INT);
3106
    /* NIP cannot be restored if the memory exception comes from an helper */
3107
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3108 3109 3110
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_temp_new_i32();
3111 3112
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
    tcg_gen_andi_i32(t1, t1, 0x7F);
A
aurel32 已提交
3113
    t2 = tcg_const_i32(rS(ctx->opcode));
3114
    gen_helper_stsw(cpu_env, t0, t1, t2);
3115 3116 3117
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3118 3119 3120 3121
}

/***                        Memory synchronisation                         ***/
/* eieio */
B
Blue Swirl 已提交
3122
static void gen_eieio(DisasContext *ctx)
B
bellard 已提交
3123 3124 3125 3126
{
}

/* isync */
B
Blue Swirl 已提交
3127
static void gen_isync(DisasContext *ctx)
B
bellard 已提交
3128
{
A
aurel32 已提交
3129
    gen_stop_exception(ctx);
B
bellard 已提交
3130 3131
}

3132
/* lwarx */
B
Blue Swirl 已提交
3133
static void gen_lwarx(DisasContext *ctx)
B
bellard 已提交
3134
{
A
aurel32 已提交
3135
    TCGv t0;
3136
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3137 3138 3139
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3140
    gen_check_align(ctx, t0, 0x03);
3141
    gen_qemu_ld32u(ctx, gpr, t0);
3142
    tcg_gen_mov_tl(cpu_reserve, t0);
3143
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3144
    tcg_temp_free(t0);
B
bellard 已提交
3145 3146
}

3147 3148 3149 3150 3151 3152 3153
#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;

3154
    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
3155
    tcg_gen_movi_tl(t0, (size << 5) | reg);
3156
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
3157 3158 3159 3160 3161 3162 3163 3164
    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 已提交
3165
/* stwcx. */
B
Blue Swirl 已提交
3166
static void gen_stwcx_(DisasContext *ctx)
B
bellard 已提交
3167
{
A
aurel32 已提交
3168 3169 3170 3171
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3172
    gen_check_align(ctx, t0, 0x03);
3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189
#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
3190
    tcg_temp_free(t0);
B
bellard 已提交
3191 3192
}

J
j_mayer 已提交
3193 3194
#if defined(TARGET_PPC64)
/* ldarx */
B
Blue Swirl 已提交
3195
static void gen_ldarx(DisasContext *ctx)
J
j_mayer 已提交
3196
{
A
aurel32 已提交
3197
    TCGv t0;
3198
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3199 3200 3201
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3202
    gen_check_align(ctx, t0, 0x07);
3203
    gen_qemu_ld64(ctx, gpr, t0);
3204
    tcg_gen_mov_tl(cpu_reserve, t0);
3205
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3206
    tcg_temp_free(t0);
J
j_mayer 已提交
3207 3208 3209
}

/* stdcx. */
B
Blue Swirl 已提交
3210
static void gen_stdcx_(DisasContext *ctx)
J
j_mayer 已提交
3211
{
A
aurel32 已提交
3212 3213 3214 3215
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3216
    gen_check_align(ctx, t0, 0x07);
3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232
#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
3233
    tcg_temp_free(t0);
J
j_mayer 已提交
3234 3235 3236
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3237
/* sync */
B
Blue Swirl 已提交
3238
static void gen_sync(DisasContext *ctx)
B
bellard 已提交
3239 3240 3241
{
}

3242
/* wait */
B
Blue Swirl 已提交
3243
static void gen_wait(DisasContext *ctx)
3244
{
3245
    TCGv_i32 t0 = tcg_temp_new_i32();
3246
    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, halted));
3247
    tcg_temp_free_i32(t0);
3248
    /* Stop translation, as the CPU is supposed to sleep from now */
A
aurel32 已提交
3249
    gen_exception_err(ctx, EXCP_HLT, 1);
3250 3251
}

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

3268
#define GEN_LDUF(name, ldop, opc, type)                                       \
B
Blue Swirl 已提交
3269
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3270
{                                                                             \
3271
    TCGv EA;                                                                  \
3272
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3273
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3274 3275
        return;                                                               \
    }                                                                         \
3276
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3277
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3278
        return;                                                               \
3279
    }                                                                         \
A
aurel32 已提交
3280
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3281
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3282 3283
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3284 3285
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3286 3287
}

3288
#define GEN_LDUXF(name, ldop, opc, type)                                      \
B
Blue Swirl 已提交
3289
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3290
{                                                                             \
3291
    TCGv EA;                                                                  \
3292
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3293
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3294 3295
        return;                                                               \
    }                                                                         \
3296
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3297
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3298
        return;                                                               \
3299
    }                                                                         \
A
aurel32 已提交
3300
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3301
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3302 3303
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3304 3305
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3306 3307
}

3308
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3309
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3310
{                                                                             \
3311
    TCGv EA;                                                                  \
3312
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3313
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3314 3315
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3316
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3317
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3318 3319
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3320
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3321 3322
}

3323 3324 3325 3326 3327 3328
#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 已提交
3329
static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3330 3331 3332
{
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
A
aurel32 已提交
3333
    gen_qemu_ld32u(ctx, t0, arg2);
3334 3335
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_temp_free(t0);
3336
    gen_helper_float32_to_float64(arg1, cpu_env, t1);
3337 3338
    tcg_temp_free_i32(t1);
}
B
bellard 已提交
3339

3340 3341 3342 3343
 /* lfd lfdu lfdux lfdx */
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3344 3345

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

3361
#define GEN_STUF(name, stop, opc, type)                                       \
B
Blue Swirl 已提交
3362
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3363
{                                                                             \
3364
    TCGv EA;                                                                  \
3365
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3366
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3367 3368
        return;                                                               \
    }                                                                         \
3369
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3370
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3371
        return;                                                               \
3372
    }                                                                         \
A
aurel32 已提交
3373
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3374
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3375 3376
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3377 3378
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3379 3380
}

3381
#define GEN_STUXF(name, stop, opc, type)                                      \
B
Blue Swirl 已提交
3382
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3383
{                                                                             \
3384
    TCGv EA;                                                                  \
3385
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3386
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3387 3388
        return;                                                               \
    }                                                                         \
3389
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3390
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3391
        return;                                                               \
3392
    }                                                                         \
A
aurel32 已提交
3393
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3394
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3395 3396
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3397 3398
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3399 3400
}

3401
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3402
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3403
{                                                                             \
3404
    TCGv EA;                                                                  \
3405
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3406
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3407 3408
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3409
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3410
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3411 3412
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3413
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3414 3415
}

3416 3417 3418 3419 3420 3421
#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 已提交
3422
static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3423 3424 3425
{
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv t1 = tcg_temp_new();
3426
    gen_helper_float64_to_float32(t0, cpu_env, arg1);
3427 3428
    tcg_gen_extu_i32_tl(t1, t0);
    tcg_temp_free_i32(t0);
A
aurel32 已提交
3429
    gen_qemu_st32(ctx, t1, arg2);
3430 3431
    tcg_temp_free(t1);
}
B
bellard 已提交
3432 3433

/* stfd stfdu stfdux stfdx */
3434
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
B
bellard 已提交
3435
/* stfs stfsu stfsux stfsx */
3436
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3437 3438

/* Optional: */
B
Blue Swirl 已提交
3439
static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3440 3441 3442
{
    TCGv t0 = tcg_temp_new();
    tcg_gen_trunc_i64_tl(t0, arg1),
A
aurel32 已提交
3443
    gen_qemu_st32(ctx, t0, arg2);
3444 3445
    tcg_temp_free(t0);
}
B
bellard 已提交
3446
/* stfiwx */
3447
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3448

D
David Gibson 已提交
3449 3450 3451 3452 3453 3454 3455 3456
static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
{
#if defined(TARGET_PPC64)
    if (ctx->has_cfar)
        tcg_gen_movi_tl(cpu_cfar, nip);
#endif
}

B
bellard 已提交
3457
/***                                Branch                                 ***/
B
Blue Swirl 已提交
3458
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3459 3460 3461
{
    TranslationBlock *tb;
    tb = ctx->tb;
3462 3463 3464 3465
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        dest = (uint32_t) dest;
#endif
B
bellard 已提交
3466
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3467
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3468
        tcg_gen_goto_tb(n);
3469
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3470
        tcg_gen_exit_tb((tcg_target_long)tb + n);
3471
    } else {
3472
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3473 3474
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3475
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
J
Julio Guerra 已提交
3476 3477
                (ctx->exception == POWERPC_EXCP_BRANCH ||
                 ctx->exception == POWERPC_EXCP_TRACE)) {
3478 3479
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
A
aurel32 已提交
3480
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3481 3482 3483
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3484
                gen_debug_exception(ctx);
3485 3486
            }
        }
B
bellard 已提交
3487
        tcg_gen_exit_tb(0);
3488
    }
B
bellard 已提交
3489 3490
}

B
Blue Swirl 已提交
3491
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3492 3493
{
#if defined(TARGET_PPC64)
3494 3495
    if (ctx->sf_mode == 0)
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3496 3497
    else
#endif
3498
        tcg_gen_movi_tl(cpu_lr, nip);
3499 3500
}

B
bellard 已提交
3501
/* b ba bl bla */
B
Blue Swirl 已提交
3502
static void gen_b(DisasContext *ctx)
B
bellard 已提交
3503
{
3504
    target_ulong li, target;
B
bellard 已提交
3505

3506
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3507
    /* sign extend LI */
3508
#if defined(TARGET_PPC64)
3509 3510 3511
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
3512
#endif
3513
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3514
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
3515
        target = ctx->nip + li - 4;
B
bellard 已提交
3516
    else
3517
        target = li;
3518 3519
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
D
David Gibson 已提交
3520
    gen_update_cfar(ctx, ctx->nip);
3521
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3522 3523
}

3524 3525 3526 3527
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

B
Blue Swirl 已提交
3528
static inline void gen_bcond(DisasContext *ctx, int type)
3529 3530
{
    uint32_t bo = BO(ctx->opcode);
3531
    int l1;
3532
    TCGv target;
3533

3534
    ctx->exception = POWERPC_EXCP_BRANCH;
3535
    if (type == BCOND_LR || type == BCOND_CTR) {
P
pbrook 已提交
3536
        target = tcg_temp_local_new();
3537 3538 3539 3540
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3541 3542
    } else {
        TCGV_UNUSED(target);
3543
    }
3544 3545
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3546 3547 3548
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3549
        TCGv temp = tcg_temp_new();
3550
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3551
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3552 3553 3554
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3555
#if defined(TARGET_PPC64)
3556 3557 3558
        if (!ctx->sf_mode)
            tcg_gen_ext32u_tl(temp, cpu_ctr);
        else
3559
#endif
3560 3561 3562 3563 3564
            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);
3565
        }
P
pbrook 已提交
3566
        tcg_temp_free(temp);
3567 3568 3569 3570 3571
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
3572
        TCGv_i32 temp = tcg_temp_new_i32();
3573

3574
        if (bo & 0x8) {
3575 3576
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3577
        } else {
3578 3579
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3580
        }
P
pbrook 已提交
3581
        tcg_temp_free_i32(temp);
3582
    }
D
David Gibson 已提交
3583
    gen_update_cfar(ctx, ctx->nip);
3584
    if (type == BCOND_IM) {
3585 3586 3587 3588 3589 3590
        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 已提交
3591
        gen_set_label(l1);
3592
        gen_goto_tb(ctx, 1, ctx->nip);
3593
    } else {
3594
#if defined(TARGET_PPC64)
3595 3596 3597 3598 3599 3600 3601 3602 3603 3604
        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);
3605 3606
        else
#endif
3607
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
B
bellard 已提交
3608
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3609
    }
3610 3611
}

B
Blue Swirl 已提交
3612
static void gen_bc(DisasContext *ctx)
3613
{
3614 3615 3616
    gen_bcond(ctx, BCOND_IM);
}

B
Blue Swirl 已提交
3617
static void gen_bcctr(DisasContext *ctx)
3618
{
3619 3620 3621
    gen_bcond(ctx, BCOND_CTR);
}

B
Blue Swirl 已提交
3622
static void gen_bclr(DisasContext *ctx)
3623
{
3624 3625
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3626 3627

/***                      Condition register logical                       ***/
3628
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
B
Blue Swirl 已提交
3629
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3630
{                                                                             \
3631 3632
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
P
pbrook 已提交
3633
    TCGv_i32 t0, t1;                                                          \
3634
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
P
pbrook 已提交
3635
    t0 = tcg_temp_new_i32();                                                  \
3636
    if (sh > 0)                                                               \
3637
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3638
    else if (sh < 0)                                                          \
3639
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3640
    else                                                                      \
3641
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
P
pbrook 已提交
3642
    t1 = tcg_temp_new_i32();                                                  \
3643 3644
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3645
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3646
    else if (sh < 0)                                                          \
3647
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3648
    else                                                                      \
3649 3650
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3651
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3652 3653 3654
    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 已提交
3655 3656
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
B
bellard 已提交
3657 3658 3659
}

/* crand */
3660
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3661
/* crandc */
3662
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3663
/* creqv */
3664
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3665
/* crnand */
3666
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3667
/* crnor */
3668
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3669
/* cror */
3670
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3671
/* crorc */
3672
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3673
/* crxor */
3674
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
Blue Swirl 已提交
3675

3676
/* mcrf */
B
Blue Swirl 已提交
3677
static void gen_mcrf(DisasContext *ctx)
B
bellard 已提交
3678
{
A
aurel32 已提交
3679
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3680 3681 3682
}

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

3684
/* rfi (mem_idx only) */
B
Blue Swirl 已提交
3685
static void gen_rfi(DisasContext *ctx)
B
bellard 已提交
3686
{
3687
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3688
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3689 3690
#else
    /* Restore CPU state */
A
aurel32 已提交
3691
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3692
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3693
        return;
3694
    }
D
David Gibson 已提交
3695
    gen_update_cfar(ctx, ctx->nip);
3696
    gen_helper_rfi(cpu_env);
A
aurel32 已提交
3697
    gen_sync_exception(ctx);
3698
#endif
B
bellard 已提交
3699 3700
}

J
j_mayer 已提交
3701
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3702
static void gen_rfid(DisasContext *ctx)
J
j_mayer 已提交
3703 3704
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3705
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3706 3707
#else
    /* Restore CPU state */
A
aurel32 已提交
3708
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3709
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3710 3711
        return;
    }
D
David Gibson 已提交
3712
    gen_update_cfar(ctx, ctx->nip);
3713
    gen_helper_rfid(cpu_env);
A
aurel32 已提交
3714
    gen_sync_exception(ctx);
J
j_mayer 已提交
3715 3716 3717
#endif
}

B
Blue Swirl 已提交
3718
static void gen_hrfid(DisasContext *ctx)
3719 3720
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3721
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3722 3723
#else
    /* Restore CPU state */
A
aurel32 已提交
3724
    if (unlikely(ctx->mem_idx <= 1)) {
A
aurel32 已提交
3725
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3726 3727
        return;
    }
3728
    gen_helper_hrfid(cpu_env);
A
aurel32 已提交
3729
    gen_sync_exception(ctx);
3730 3731 3732 3733
#endif
}
#endif

B
bellard 已提交
3734
/* sc */
3735 3736 3737 3738 3739
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
B
Blue Swirl 已提交
3740
static void gen_sc(DisasContext *ctx)
B
bellard 已提交
3741
{
3742 3743 3744
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
A
aurel32 已提交
3745
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3746 3747 3748
}

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

3750
/* tw */
B
Blue Swirl 已提交
3751
static void gen_tw(DisasContext *ctx)
B
bellard 已提交
3752
{
3753
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3754 3755
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3756 3757
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3758
    tcg_temp_free_i32(t0);
B
bellard 已提交
3759 3760 3761
}

/* twi */
B
Blue Swirl 已提交
3762
static void gen_twi(DisasContext *ctx)
B
bellard 已提交
3763
{
3764 3765
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3766 3767
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3768
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3769 3770
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3771 3772
}

3773 3774
#if defined(TARGET_PPC64)
/* td */
B
Blue Swirl 已提交
3775
static void gen_td(DisasContext *ctx)
3776
{
3777
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3778 3779
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3780 3781
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3782
    tcg_temp_free_i32(t0);
3783 3784 3785
}

/* tdi */
B
Blue Swirl 已提交
3786
static void gen_tdi(DisasContext *ctx)
3787
{
3788 3789
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3790 3791
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3792
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3793 3794
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
3795 3796 3797
}
#endif

B
bellard 已提交
3798
/***                          Processor control                            ***/
B
Blue Swirl 已提交
3799

3800
/* mcrxr */
B
Blue Swirl 已提交
3801
static void gen_mcrxr(DisasContext *ctx)
B
bellard 已提交
3802
{
A
aurel32 已提交
3803 3804
    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);
3805
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
B
bellard 已提交
3806 3807
}

A
aurel32 已提交
3808
/* mfcr mfocrf */
B
Blue Swirl 已提交
3809
static void gen_mfcr(DisasContext *ctx)
B
bellard 已提交
3810
{
3811
    uint32_t crm, crn;
3812

3813 3814
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3815
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3816
            crn = ctz32 (crm);
3817
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3818 3819
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3820
        }
3821
    } else {
A
aurel32 已提交
3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839
        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);
3840
    }
B
bellard 已提交
3841 3842 3843
}

/* mfmsr */
B
Blue Swirl 已提交
3844
static void gen_mfmsr(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
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3854
#endif
B
bellard 已提交
3855 3856
}

3857
static void spr_noaccess(void *opaque, int gprn, int sprn)
3858
{
3859
#if 0
3860 3861
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
3862
#endif
3863 3864 3865
}
#define SPR_NOACCESS (&spr_noaccess)

B
bellard 已提交
3866
/* mfspr */
B
Blue Swirl 已提交
3867
static inline void gen_op_mfspr(DisasContext *ctx)
B
bellard 已提交
3868
{
A
aurel32 已提交
3869
    void (*read_cb)(void *opaque, int gprn, int sprn);
B
bellard 已提交
3870 3871
    uint32_t sprn = SPR(ctx->opcode);

3872
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3873
    if (ctx->mem_idx == 2)
3874
        read_cb = ctx->spr_cb[sprn].hea_read;
A
aurel32 已提交
3875
    else if (ctx->mem_idx)
3876 3877
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3878
#endif
3879
        read_cb = ctx->spr_cb[sprn].uea_read;
3880 3881
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3882
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3883 3884
        } else {
            /* Privilege exception */
3885 3886 3887 3888 3889
            /* 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) {
3890
                qemu_log("Trying to read privileged spr %d %03x at "
3891 3892 3893
                         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);
3894
            }
A
aurel32 已提交
3895
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
3896
        }
3897 3898
    } else {
        /* Not defined */
3899
        qemu_log("Trying to read invalid spr %d %03x at "
3900 3901
                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
3902
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3903
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3904 3905 3906
    }
}

B
Blue Swirl 已提交
3907
static void gen_mfspr(DisasContext *ctx)
B
bellard 已提交
3908
{
3909
    gen_op_mfspr(ctx);
3910
}
3911 3912

/* mftb */
B
Blue Swirl 已提交
3913
static void gen_mftb(DisasContext *ctx)
3914 3915
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3916 3917
}

A
aurel32 已提交
3918
/* mtcrf mtocrf*/
B
Blue Swirl 已提交
3919
static void gen_mtcrf(DisasContext *ctx)
B
bellard 已提交
3920
{
3921
    uint32_t crm, crn;
3922

3923
    crm = CRM(ctx->opcode);
M
malc 已提交
3924 3925 3926
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
3927
            crn = ctz32 (crm);
M
malc 已提交
3928
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
3929 3930
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
3931 3932
            tcg_temp_free_i32(temp);
        }
3933
    } else {
A
aurel32 已提交
3934 3935 3936 3937 3938 3939 3940 3941
        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 已提交
3942
        tcg_temp_free_i32(temp);
3943
    }
B
bellard 已提交
3944 3945 3946
}

/* mtmsr */
J
j_mayer 已提交
3947
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3948
static void gen_mtmsrd(DisasContext *ctx)
J
j_mayer 已提交
3949 3950
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3951
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3952
#else
A
aurel32 已提交
3953
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3954
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3955 3956
        return;
    }
3957 3958
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3959 3960 3961 3962 3963
        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);
3964
    } else {
3965 3966 3967 3968
        /* XXX: we need to update nip before the store
         *      if we enter power saving mode, we will exit the loop
         *      directly from ppc_store_msr
         */
3969
        gen_update_nip(ctx, ctx->nip);
3970
        gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
3971 3972
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3973
        gen_stop_exception(ctx);
3974
    }
J
j_mayer 已提交
3975 3976 3977 3978
#endif
}
#endif

B
Blue Swirl 已提交
3979
static void gen_mtmsr(DisasContext *ctx)
B
bellard 已提交
3980
{
3981
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3982
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3983
#else
A
aurel32 已提交
3984
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3985
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3986
        return;
3987
    }
3988 3989
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3990 3991 3992 3993 3994
        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);
3995
    } else {
3996 3997
        TCGv msr = tcg_temp_new();

3998 3999 4000 4001
        /* 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
         */
4002
        gen_update_nip(ctx, ctx->nip);
4003
#if defined(TARGET_PPC64)
4004 4005 4006
        tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
#else
        tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
4007
#endif
4008
        gen_helper_store_msr(cpu_env, msr);
4009
        /* Must stop the translation as machine state (may have) changed */
4010
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
4011
        gen_stop_exception(ctx);
4012
    }
4013
#endif
B
bellard 已提交
4014 4015 4016
}

/* mtspr */
B
Blue Swirl 已提交
4017
static void gen_mtspr(DisasContext *ctx)
B
bellard 已提交
4018
{
A
aurel32 已提交
4019
    void (*write_cb)(void *opaque, int sprn, int gprn);
B
bellard 已提交
4020 4021
    uint32_t sprn = SPR(ctx->opcode);

4022
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4023
    if (ctx->mem_idx == 2)
4024
        write_cb = ctx->spr_cb[sprn].hea_write;
A
aurel32 已提交
4025
    else if (ctx->mem_idx)
4026 4027
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
4028
#endif
4029
        write_cb = ctx->spr_cb[sprn].uea_write;
4030 4031
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
4032
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
4033 4034
        } else {
            /* Privilege exception */
4035
            qemu_log("Trying to write privileged spr %d %03x at "
4036 4037 4038
                     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 已提交
4039
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4040
        }
4041 4042
    } else {
        /* Not defined */
4043
        qemu_log("Trying to write invalid spr %d %03x at "
4044 4045
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
        printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
J
j_mayer 已提交
4046
               sprn, sprn, ctx->nip);
A
aurel32 已提交
4047
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
4048 4049 4050 4051
    }
}

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

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

/* dcbi (Supervisor only) */
B
Blue Swirl 已提交
4066
static void gen_dcbi(DisasContext *ctx)
B
bellard 已提交
4067
{
4068
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4069
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4070
#else
A
aurel32 已提交
4071
    TCGv EA, val;
A
aurel32 已提交
4072
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4073
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4074
        return;
4075
    }
P
pbrook 已提交
4076
    EA = tcg_temp_new();
A
aurel32 已提交
4077 4078
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
4079
    val = tcg_temp_new();
4080
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
4081 4082
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
4083 4084
    tcg_temp_free(val);
    tcg_temp_free(EA);
4085
#endif
B
bellard 已提交
4086 4087 4088
}

/* dcdst */
B
Blue Swirl 已提交
4089
static void gen_dcbst(DisasContext *ctx)
B
bellard 已提交
4090
{
4091
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
4092 4093 4094 4095 4096
    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);
4097
    tcg_temp_free(t0);
B
bellard 已提交
4098 4099 4100
}

/* dcbt */
B
Blue Swirl 已提交
4101
static void gen_dcbt(DisasContext *ctx)
B
bellard 已提交
4102
{
4103
    /* interpreted as no-op */
4104 4105 4106
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4107 4108 4109
}

/* dcbtst */
B
Blue Swirl 已提交
4110
static void gen_dcbtst(DisasContext *ctx)
B
bellard 已提交
4111
{
4112
    /* interpreted as no-op */
4113 4114 4115
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4116 4117 4118
}

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

B
Blue Swirl 已提交
4131
static void gen_dcbz_970(DisasContext *ctx)
4132
{
A
aurel32 已提交
4133 4134
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4135 4136
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4137 4138
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4139
    if (ctx->opcode & 0x00200000)
4140
        gen_helper_dcbz(cpu_env, t0);
4141
    else
4142
        gen_helper_dcbz_970(cpu_env, t0);
4143
    tcg_temp_free(t0);
B
bellard 已提交
4144 4145
}

4146
/* dst / dstt */
B
Blue Swirl 已提交
4147
static void gen_dst(DisasContext *ctx)
4148 4149 4150 4151 4152 4153 4154 4155 4156
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }
}

/* dstst /dststt */
B
Blue Swirl 已提交
4157
static void gen_dstst(DisasContext *ctx)
4158 4159 4160 4161 4162 4163 4164 4165 4166 4167
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }

}

/* dss / dssall */
B
Blue Swirl 已提交
4168
static void gen_dss(DisasContext *ctx)
4169 4170 4171 4172
{
    /* interpreted as no-op */
}

B
bellard 已提交
4173
/* icbi */
B
Blue Swirl 已提交
4174
static void gen_icbi(DisasContext *ctx)
B
bellard 已提交
4175
{
A
aurel32 已提交
4176 4177
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4178 4179
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4180 4181
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4182
    gen_helper_icbi(cpu_env, t0);
4183
    tcg_temp_free(t0);
B
bellard 已提交
4184 4185 4186 4187
}

/* Optional: */
/* dcba */
B
Blue Swirl 已提交
4188
static void gen_dcba(DisasContext *ctx)
B
bellard 已提交
4189
{
4190 4191 4192 4193
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4194 4195 4196 4197
}

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

4199
/* mfsr */
B
Blue Swirl 已提交
4200
static void gen_mfsr(DisasContext *ctx)
B
bellard 已提交
4201
{
4202
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4203
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4204
#else
4205
    TCGv t0;
A
aurel32 已提交
4206
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4207
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4208
        return;
4209
    }
4210
    t0 = tcg_const_tl(SR(ctx->opcode));
4211
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4212
    tcg_temp_free(t0);
4213
#endif
B
bellard 已提交
4214 4215 4216
}

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

/* mtsr */
B
Blue Swirl 已提交
4236
static void gen_mtsr(DisasContext *ctx)
B
bellard 已提交
4237
{
4238
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4239
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4240
#else
4241
    TCGv t0;
A
aurel32 已提交
4242
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4243
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4244
        return;
4245
    }
4246
    t0 = tcg_const_tl(SR(ctx->opcode));
4247
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4248
    tcg_temp_free(t0);
4249
#endif
B
bellard 已提交
4250 4251 4252
}

/* mtsrin */
B
Blue Swirl 已提交
4253
static void gen_mtsrin(DisasContext *ctx)
B
bellard 已提交
4254
{
4255
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4256
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4257
#else
4258
    TCGv t0;
A
aurel32 已提交
4259
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4260
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4261
        return;
4262
    }
4263 4264 4265
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4266
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
4267
    tcg_temp_free(t0);
4268
#endif
B
bellard 已提交
4269 4270
}

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

4274
/* mfsr */
B
Blue Swirl 已提交
4275
static void gen_mfsr_64b(DisasContext *ctx)
4276 4277
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4278
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4279
#else
4280
    TCGv t0;
A
aurel32 已提交
4281
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4282
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4283 4284
        return;
    }
4285
    t0 = tcg_const_tl(SR(ctx->opcode));
4286
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4287
    tcg_temp_free(t0);
4288 4289 4290 4291
#endif
}

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

/* mtsr */
B
Blue Swirl 已提交
4311
static void gen_mtsr_64b(DisasContext *ctx)
4312 4313
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4314
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4315
#else
4316
    TCGv t0;
A
aurel32 已提交
4317
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4318
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4319 4320
        return;
    }
4321
    t0 = tcg_const_tl(SR(ctx->opcode));
4322
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4323
    tcg_temp_free(t0);
4324 4325 4326 4327
#endif
}

/* mtsrin */
B
Blue Swirl 已提交
4328
static void gen_mtsrin_64b(DisasContext *ctx)
4329 4330
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4331
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4332
#else
4333
    TCGv t0;
A
aurel32 已提交
4334
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4335
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4336 4337
        return;
    }
4338 4339 4340
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4341
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4342
    tcg_temp_free(t0);
4343 4344
#endif
}
B
blueswir1 已提交
4345 4346

/* slbmte */
B
Blue Swirl 已提交
4347
static void gen_slbmte(DisasContext *ctx)
B
blueswir1 已提交
4348 4349 4350 4351 4352 4353 4354 4355
{
#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;
    }
4356 4357
    gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
B
blueswir1 已提交
4358 4359 4360
#endif
}

4361 4362 4363 4364 4365 4366 4367 4368 4369
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;
    }
4370
    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383
                             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;
    }
4384
    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4385 4386 4387
                             cpu_gpr[rB(ctx->opcode)]);
#endif
}
4388 4389
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4390
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4391
/* Optional & mem_idx only: */
B
Blue Swirl 已提交
4392

4393
/* tlbia */
B
Blue Swirl 已提交
4394
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4395
{
4396
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4397
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4398
#else
A
aurel32 已提交
4399
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4400
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4401
        return;
4402
    }
4403
    gen_helper_tlbia(cpu_env);
4404
#endif
B
bellard 已提交
4405 4406
}

B
blueswir1 已提交
4407
/* tlbiel */
B
Blue Swirl 已提交
4408
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4409 4410 4411 4412 4413 4414 4415 4416
{
#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;
    }
4417
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
B
blueswir1 已提交
4418 4419 4420
#endif
}

B
bellard 已提交
4421
/* tlbie */
B
Blue Swirl 已提交
4422
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4423
{
4424
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4425
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4426
#else
A
aurel32 已提交
4427
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4428
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4429
        return;
4430
    }
4431
#if defined(TARGET_PPC64)
4432 4433 4434
    if (!ctx->sf_mode) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4435
        gen_helper_tlbie(cpu_env, t0);
4436 4437
        tcg_temp_free(t0);
    } else
4438
#endif
4439
        gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4440
#endif
B
bellard 已提交
4441 4442 4443
}

/* tlbsync */
B
Blue Swirl 已提交
4444
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4445
{
4446
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4447
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4448
#else
A
aurel32 已提交
4449
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4450
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4451
        return;
4452 4453 4454 4455
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4456
    gen_stop_exception(ctx);
4457
#endif
B
bellard 已提交
4458 4459
}

J
j_mayer 已提交
4460 4461
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4462
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4463 4464
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4465
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4466
#else
A
aurel32 已提交
4467
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4468
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4469 4470
        return;
    }
4471
    gen_helper_slbia(cpu_env);
J
j_mayer 已提交
4472 4473 4474 4475
#endif
}

/* slbie */
B
Blue Swirl 已提交
4476
static void gen_slbie(DisasContext *ctx)
J
j_mayer 已提交
4477 4478
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4479
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4480
#else
A
aurel32 已提交
4481
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4482
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4483 4484
        return;
    }
4485
    gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4486 4487 4488 4489
#endif
}
#endif

B
bellard 已提交
4490 4491
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4492

4493
/* eciwx */
B
Blue Swirl 已提交
4494
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4495
{
A
aurel32 已提交
4496
    TCGv t0;
4497
    /* Should check EAR[E] ! */
A
aurel32 已提交
4498 4499 4500
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4501
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4502
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4503
    tcg_temp_free(t0);
4504 4505 4506
}

/* ecowx */
B
Blue Swirl 已提交
4507
static void gen_ecowx(DisasContext *ctx)
4508
{
A
aurel32 已提交
4509
    TCGv t0;
4510
    /* Should check EAR[E] ! */
A
aurel32 已提交
4511 4512 4513
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4514
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4515
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4516
    tcg_temp_free(t0);
4517 4518 4519
}

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

4521
/* abs - abs. */
B
Blue Swirl 已提交
4522
static void gen_abs(DisasContext *ctx)
4523
{
4524 4525 4526 4527 4528 4529 4530 4531
    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);
4532
    if (unlikely(Rc(ctx->opcode) != 0))
4533
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4534 4535 4536
}

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

/* clcs */
B
Blue Swirl 已提交
4559
static void gen_clcs(DisasContext *ctx)
4560
{
4561
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
B
Blue Swirl 已提交
4562
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4563
    tcg_temp_free_i32(t0);
4564
    /* Rc=1 sets CR0 to an undefined state */
4565 4566 4567
}

/* div - div. */
B
Blue Swirl 已提交
4568
static void gen_div(DisasContext *ctx)
4569
{
4570 4571
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
4572
    if (unlikely(Rc(ctx->opcode) != 0))
4573
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4574 4575 4576
}

/* divo - divo. */
B
Blue Swirl 已提交
4577
static void gen_divo(DisasContext *ctx)
4578
{
4579 4580
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4581
    if (unlikely(Rc(ctx->opcode) != 0))
4582
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4583 4584 4585
}

/* divs - divs. */
B
Blue Swirl 已提交
4586
static void gen_divs(DisasContext *ctx)
4587
{
4588 4589
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4590
    if (unlikely(Rc(ctx->opcode) != 0))
4591
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4592 4593 4594
}

/* divso - divso. */
B
Blue Swirl 已提交
4595
static void gen_divso(DisasContext *ctx)
4596
{
4597 4598
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4599
    if (unlikely(Rc(ctx->opcode) != 0))
4600
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4601 4602 4603
}

/* doz - doz. */
B
Blue Swirl 已提交
4604
static void gen_doz(DisasContext *ctx)
4605
{
4606 4607 4608 4609 4610 4611 4612 4613
    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);
4614
    if (unlikely(Rc(ctx->opcode) != 0))
4615
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4616 4617 4618
}

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

/* dozi */
B
Blue Swirl 已提交
4648
static void gen_dozi(DisasContext *ctx)
4649
{
4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660
    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)]);
4661 4662 4663
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4664
static void gen_lscbx(DisasContext *ctx)
4665
{
4666 4667 4668 4669
    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));
4670

A
aurel32 已提交
4671
    gen_addr_reg_index(ctx, t0);
4672
    /* NIP cannot be restored if the memory exception comes from an helper */
4673
    gen_update_nip(ctx, ctx->nip - 4);
4674
    gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
4675 4676 4677
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
A
aurel32 已提交
4678
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4679
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4680
    if (unlikely(Rc(ctx->opcode) != 0))
4681 4682
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4683 4684 4685
}

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

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

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

/* mulo - mulo. */
B
Blue Swirl 已提交
4746
static void gen_mulo(DisasContext *ctx)
4747
{
4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767
    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);
4768
    if (unlikely(Rc(ctx->opcode) != 0))
4769
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4770 4771 4772
}

/* nabs - nabs. */
B
Blue Swirl 已提交
4773
static void gen_nabs(DisasContext *ctx)
4774
{
4775 4776 4777 4778 4779 4780 4781 4782
    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);
4783
    if (unlikely(Rc(ctx->opcode) != 0))
4784
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4785 4786 4787
}

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

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

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

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

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

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

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

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

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

4965
/* sraiq - sraiq. */
B
Blue Swirl 已提交
4966
static void gen_sraiq(DisasContext *ctx)
4967
{
4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983
    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);
4984
    if (unlikely(Rc(ctx->opcode) != 0))
4985
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4986 4987 4988
}

/* sraq - sraq. */
B
Blue Swirl 已提交
4989
static void gen_sraq(DisasContext *ctx)
4990
{
4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016
    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);
5017
    if (unlikely(Rc(ctx->opcode) != 0))
5018
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5019 5020 5021
}

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

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

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

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

/* srliq */
B
Blue Swirl 已提交
5094
static void gen_srliq(DisasContext *ctx)
5095
{
5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106
    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);
5107
    if (unlikely(Rc(ctx->opcode) != 0))
5108
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5109 5110 5111
}

/* srlq */
B
Blue Swirl 已提交
5112
static void gen_srlq(DisasContext *ctx)
5113
{
5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136
    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);
5137
    if (unlikely(Rc(ctx->opcode) != 0))
5138
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5139 5140 5141
}

/* srq */
B
Blue Swirl 已提交
5142
static void gen_srq(DisasContext *ctx)
5143
{
5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159
    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);
5160
    if (unlikely(Rc(ctx->opcode) != 0))
5161
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5162 5163 5164
}

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

5166
/* dsa  */
B
Blue Swirl 已提交
5167
static void gen_dsa(DisasContext *ctx)
5168 5169
{
    /* XXX: TODO */
A
aurel32 已提交
5170
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5171 5172 5173
}

/* esa */
B
Blue Swirl 已提交
5174
static void gen_esa(DisasContext *ctx)
5175 5176
{
    /* XXX: TODO */
A
aurel32 已提交
5177
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5178 5179 5180
}

/* mfrom */
B
Blue Swirl 已提交
5181
static void gen_mfrom(DisasContext *ctx)
5182 5183
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5184
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5185
#else
A
aurel32 已提交
5186
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5187
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5188 5189
        return;
    }
5190
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5191 5192 5193 5194
#endif
}

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

5196
/* tlbld */
B
Blue Swirl 已提交
5197
static void gen_tlbld_6xx(DisasContext *ctx)
5198 5199
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5200
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5201
#else
A
aurel32 已提交
5202
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5203
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5204 5205
        return;
    }
5206
    gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5207 5208 5209 5210
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5211
static void gen_tlbli_6xx(DisasContext *ctx)
5212 5213
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5214
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5215
#else
A
aurel32 已提交
5216
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5217
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5218 5219
        return;
    }
5220
    gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5221 5222 5223
#endif
}

5224
/* 74xx TLB management */
B
Blue Swirl 已提交
5225

5226
/* tlbld */
B
Blue Swirl 已提交
5227
static void gen_tlbld_74xx(DisasContext *ctx)
5228 5229
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5230
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5231
#else
A
aurel32 已提交
5232
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5233
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5234 5235
        return;
    }
5236
    gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5237 5238 5239 5240
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5241
static void gen_tlbli_74xx(DisasContext *ctx)
5242 5243
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5244
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5245
#else
A
aurel32 已提交
5246
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5247
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5248 5249
        return;
    }
5250
    gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5251 5252 5253
#endif
}

5254
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5255

5256
/* clf */
B
Blue Swirl 已提交
5257
static void gen_clf(DisasContext *ctx)
5258 5259 5260 5261 5262
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5263
static void gen_cli(DisasContext *ctx)
5264
{
B
blueswir1 已提交
5265
    /* Cache line invalidate: privileged and treated as no-op */
5266
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5267
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5268
#else
A
aurel32 已提交
5269
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5270
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5271 5272 5273 5274 5275 5276
        return;
    }
#endif
}

/* dclst */
B
Blue Swirl 已提交
5277
static void gen_dclst(DisasContext *ctx)
5278 5279 5280 5281
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5282
static void gen_mfsri(DisasContext *ctx)
5283 5284
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5285
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5286
#else
5287 5288 5289
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5290
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5291
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5292 5293
        return;
    }
5294
    t0 = tcg_temp_new();
A
aurel32 已提交
5295
    gen_addr_reg_index(ctx, t0);
5296 5297
    tcg_gen_shri_tl(t0, t0, 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
5298
    gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
5299
    tcg_temp_free(t0);
5300
    if (ra != 0 && ra != rd)
5301
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5302 5303 5304
#endif
}

B
Blue Swirl 已提交
5305
static void gen_rac(DisasContext *ctx)
5306 5307
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5308
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5309
#else
5310
    TCGv t0;
A
aurel32 已提交
5311
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5312
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5313 5314
        return;
    }
5315
    t0 = tcg_temp_new();
A
aurel32 已提交
5316
    gen_addr_reg_index(ctx, t0);
5317
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5318
    tcg_temp_free(t0);
5319 5320 5321
#endif
}

B
Blue Swirl 已提交
5322
static void gen_rfsvc(DisasContext *ctx)
5323 5324
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5325
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5326
#else
A
aurel32 已提交
5327
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5328
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5329 5330
        return;
    }
5331
    gen_helper_rfsvc(cpu_env);
A
aurel32 已提交
5332
    gen_sync_exception(ctx);
5333 5334 5335 5336 5337 5338 5339 5340 5341
#endif
}

/* svc is not implemented for now */

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

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

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

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

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

/* stfq */
B
Blue Swirl 已提交
5408
static void gen_stfq(DisasContext *ctx)
5409
{
5410
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5411 5412 5413 5414 5415 5416 5417
    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);
5418
    tcg_temp_free(t0);
5419 5420 5421
}

/* stfqu */
B
Blue Swirl 已提交
5422
static void gen_stfqu(DisasContext *ctx)
5423 5424
{
    int ra = rA(ctx->opcode);
5425
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5426 5427 5428 5429 5430 5431 5432 5433 5434
    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);
5435
    if (ra != 0)
5436 5437
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5438 5439 5440
}

/* stfqux */
B
Blue Swirl 已提交
5441
static void gen_stfqux(DisasContext *ctx)
5442 5443
{
    int ra = rA(ctx->opcode);
5444
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5445 5446 5447 5448 5449 5450 5451 5452 5453
    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);
5454
    if (ra != 0)
5455 5456
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5457 5458 5459
}

/* stfqx */
B
Blue Swirl 已提交
5460
static void gen_stfqx(DisasContext *ctx)
5461
{
5462
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5463 5464 5465 5466 5467 5468 5469
    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);
5470
    tcg_temp_free(t0);
5471 5472 5473
}

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

5475
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5476
static void gen_mfapidi(DisasContext *ctx)
5477 5478
{
    /* XXX: TODO */
A
aurel32 已提交
5479
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5480 5481
}

5482
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5483
static void gen_tlbiva(DisasContext *ctx)
5484 5485
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5486
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5487
#else
5488
    TCGv t0;
A
aurel32 已提交
5489
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5490
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5491 5492
        return;
    }
5493
    t0 = tcg_temp_new();
A
aurel32 已提交
5494
    gen_addr_reg_index(ctx, t0);
5495
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5496
    tcg_temp_free(t0);
5497 5498 5499 5500
#endif
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5501 5502
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5503
{
5504 5505
    TCGv t0, t1;

P
pbrook 已提交
5506 5507
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5508

5509 5510 5511 5512 5513 5514 5515
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5516 5517 5518
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5519 5520 5521 5522 5523
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5524 5525 5526
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5527 5528 5529 5530 5531 5532 5533
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5534 5535 5536 5537
        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);
5538 5539 5540 5541 5542
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5543 5544 5545 5546
        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);
5547 5548 5549 5550 5551 5552 5553
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5554 5555
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5556 5557 5558 5559 5560
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5561 5562
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5563 5564 5565
        break;
    }
    if (opc2 & 0x04) {
5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589
        /* (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 已提交
5590
                if (opc3 & 0x02) {
5591 5592 5593 5594 5595 5596 5597
                    /* 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 已提交
5598
                if (opc3 & 0x02) {
5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611
                    /* 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);
5612
    }
5613 5614
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5615 5616
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5617
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5618 5619 5620
    }
}

5621
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5622
static void glue(gen_, name)(DisasContext *ctx)                               \
5623 5624 5625 5626 5627 5628
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5629
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5630
/* macchwo   - macchwo.   */
5631
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5632
/* macchws   - macchws.   */
5633
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5634
/* macchwso  - macchwso.  */
5635
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5636
/* macchwsu  - macchwsu.  */
5637
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5638
/* macchwsuo - macchwsuo. */
5639
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5640
/* macchwu   - macchwu.   */
5641
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5642
/* macchwuo  - macchwuo.  */
5643
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5644
/* machhw    - machhw.    */
5645
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5646
/* machhwo   - machhwo.   */
5647
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5648
/* machhws   - machhws.   */
5649
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5650
/* machhwso  - machhwso.  */
5651
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5652
/* machhwsu  - machhwsu.  */
5653
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5654
/* machhwsuo - machhwsuo. */
5655
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5656
/* machhwu   - machhwu.   */
5657
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5658
/* machhwuo  - machhwuo.  */
5659
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5660
/* maclhw    - maclhw.    */
5661
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5662
/* maclhwo   - maclhwo.   */
5663
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5664
/* maclhws   - maclhws.   */
5665
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5666
/* maclhwso  - maclhwso.  */
5667
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5668
/* maclhwu   - maclhwu.   */
5669
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5670
/* maclhwuo  - maclhwuo.  */
5671
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5672
/* maclhwsu  - maclhwsu.  */
5673
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5674
/* maclhwsuo - maclhwsuo. */
5675
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5676
/* nmacchw   - nmacchw.   */
5677
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5678
/* nmacchwo  - nmacchwo.  */
5679
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5680
/* nmacchws  - nmacchws.  */
5681
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5682
/* nmacchwso - nmacchwso. */
5683
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5684
/* nmachhw   - nmachhw.   */
5685
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5686
/* nmachhwo  - nmachhwo.  */
5687
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5688
/* nmachhws  - nmachhws.  */
5689
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5690
/* nmachhwso - nmachhwso. */
5691
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5692
/* nmaclhw   - nmaclhw.   */
5693
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5694
/* nmaclhwo  - nmaclhwo.  */
5695
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5696
/* nmaclhws  - nmaclhws.  */
5697
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5698
/* nmaclhwso - nmaclhwso. */
5699
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5700 5701

/* mulchw  - mulchw.  */
5702
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5703
/* mulchwu - mulchwu. */
5704
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5705
/* mulhhw  - mulhhw.  */
5706
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5707
/* mulhhwu - mulhhwu. */
5708
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5709
/* mullhw  - mullhw.  */
5710
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5711
/* mullhwu - mullhwu. */
5712
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5713 5714

/* mfdcr */
B
Blue Swirl 已提交
5715
static void gen_mfdcr(DisasContext *ctx)
5716 5717
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5718
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5719
#else
5720
    TCGv dcrn;
A
aurel32 已提交
5721
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5722
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5723 5724
        return;
    }
5725 5726 5727
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5728
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
5729
    tcg_temp_free(dcrn);
5730 5731 5732 5733
#endif
}

/* mtdcr */
B
Blue Swirl 已提交
5734
static void gen_mtdcr(DisasContext *ctx)
5735 5736
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5737
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5738
#else
5739
    TCGv dcrn;
A
aurel32 已提交
5740
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5741
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5742 5743
        return;
    }
5744 5745 5746
    /* 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));
5747
    gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
5748
    tcg_temp_free(dcrn);
5749 5750 5751 5752
#endif
}

/* mfdcrx */
5753
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5754
static void gen_mfdcrx(DisasContext *ctx)
5755 5756
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5757
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5758
#else
A
aurel32 已提交
5759
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5760
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5761 5762
        return;
    }
5763 5764
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5765 5766
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5767
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5768 5769 5770 5771
#endif
}

/* mtdcrx */
5772
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5773
static void gen_mtdcrx(DisasContext *ctx)
5774 5775
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5776
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5777
#else
A
aurel32 已提交
5778
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5779
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5780 5781
        return;
    }
5782 5783
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5784 5785
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
5786
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5787 5788 5789
#endif
}

5790
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5791
static void gen_mfdcrux(DisasContext *ctx)
5792
{
5793 5794
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5795 5796
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5797 5798 5799 5800
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5801
static void gen_mtdcrux(DisasContext *ctx)
5802
{
5803 5804
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5805
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
5806
                         cpu_gpr[rS(ctx->opcode)]);
5807 5808 5809
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5810
/* dccci */
B
Blue Swirl 已提交
5811
static void gen_dccci(DisasContext *ctx)
5812 5813
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5814
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5815
#else
A
aurel32 已提交
5816
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5817
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5818 5819 5820 5821 5822 5823 5824
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
B
Blue Swirl 已提交
5825
static void gen_dcread(DisasContext *ctx)
5826 5827
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5828
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5829
#else
A
aurel32 已提交
5830
    TCGv EA, val;
A
aurel32 已提交
5831
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5832
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5833 5834
        return;
    }
A
aurel32 已提交
5835
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5836
    EA = tcg_temp_new();
A
aurel32 已提交
5837
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5838
    val = tcg_temp_new();
A
aurel32 已提交
5839
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5840 5841 5842
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5843 5844 5845 5846
#endif
}

/* icbt */
B
Blue Swirl 已提交
5847
static void gen_icbt_40x(DisasContext *ctx)
5848 5849 5850 5851 5852 5853 5854 5855
{
    /* 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 已提交
5856
static void gen_iccci(DisasContext *ctx)
5857 5858
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5859
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5860
#else
A
aurel32 已提交
5861
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5862
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5863 5864 5865 5866 5867 5868 5869
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
B
Blue Swirl 已提交
5870
static void gen_icread(DisasContext *ctx)
5871 5872
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5873
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5874
#else
A
aurel32 已提交
5875
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5876
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5877 5878 5879 5880 5881 5882
        return;
    }
    /* interpreted as no-op */
#endif
}

A
aurel32 已提交
5883
/* rfci (mem_idx only) */
B
Blue Swirl 已提交
5884
static void gen_rfci_40x(DisasContext *ctx)
5885 5886
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5887
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5888
#else
A
aurel32 已提交
5889
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5890
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5891 5892 5893
        return;
    }
    /* Restore CPU state */
5894
    gen_helper_40x_rfci(cpu_env);
A
aurel32 已提交
5895
    gen_sync_exception(ctx);
5896 5897 5898
#endif
}

B
Blue Swirl 已提交
5899
static void gen_rfci(DisasContext *ctx)
5900 5901
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5902
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5903
#else
A
aurel32 已提交
5904
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5905
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5906 5907 5908
        return;
    }
    /* Restore CPU state */
5909
    gen_helper_rfci(cpu_env);
A
aurel32 已提交
5910
    gen_sync_exception(ctx);
5911 5912 5913 5914
#endif
}

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

5916
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5917
static void gen_rfdi(DisasContext *ctx)
5918 5919
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5920
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5921
#else
A
aurel32 已提交
5922
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5923
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5924 5925 5926
        return;
    }
    /* Restore CPU state */
5927
    gen_helper_rfdi(cpu_env);
A
aurel32 已提交
5928
    gen_sync_exception(ctx);
5929 5930 5931
#endif
}

5932
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5933
static void gen_rfmci(DisasContext *ctx)
5934 5935
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5936
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5937
#else
A
aurel32 已提交
5938
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5939
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5940 5941 5942
        return;
    }
    /* Restore CPU state */
5943
    gen_helper_rfmci(cpu_env);
A
aurel32 已提交
5944
    gen_sync_exception(ctx);
5945 5946
#endif
}
5947

5948
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5949

5950
/* tlbre */
B
Blue Swirl 已提交
5951
static void gen_tlbre_40x(DisasContext *ctx)
5952 5953
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5954
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5955
#else
A
aurel32 已提交
5956
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5957
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5958 5959 5960 5961
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5962 5963
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
5964 5965
        break;
    case 1:
5966 5967
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
5968 5969
        break;
    default:
A
aurel32 已提交
5970
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5971
        break;
5972
    }
5973 5974 5975
#endif
}

5976
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5977
static void gen_tlbsx_40x(DisasContext *ctx)
5978 5979
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5980
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5981
#else
5982
    TCGv t0;
A
aurel32 已提交
5983
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5984
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5985 5986
        return;
    }
5987
    t0 = tcg_temp_new();
A
aurel32 已提交
5988
    gen_addr_reg_index(ctx, t0);
5989
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5990 5991 5992 5993 5994 5995 5996 5997 5998 5999
    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);
    }
6000
#endif
B
bellard 已提交
6001 6002
}

6003
/* tlbwe */
B
Blue Swirl 已提交
6004
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
6005
{
6006
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6007
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6008
#else
A
aurel32 已提交
6009
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6010
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6011 6012 6013 6014
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
6015 6016
        gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
6017 6018
        break;
    case 1:
6019 6020
        gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
6021 6022
        break;
    default:
A
aurel32 已提交
6023
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6024
        break;
6025
    }
6026 6027 6028
#endif
}

6029
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
6030

6031
/* tlbre */
B
Blue Swirl 已提交
6032
static void gen_tlbre_440(DisasContext *ctx)
6033 6034
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6035
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6036
#else
A
aurel32 已提交
6037
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6038
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6039 6040 6041 6042 6043 6044
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6045 6046
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6047 6048
            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                 t0, cpu_gpr[rA(ctx->opcode)]);
6049 6050
            tcg_temp_free_i32(t0);
        }
6051 6052
        break;
    default:
A
aurel32 已提交
6053
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6054 6055 6056 6057 6058 6059
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
6060
static void gen_tlbsx_440(DisasContext *ctx)
6061 6062
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6063
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6064
#else
6065
    TCGv t0;
A
aurel32 已提交
6066
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6067
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6068 6069
        return;
    }
6070
    t0 = tcg_temp_new();
A
aurel32 已提交
6071
    gen_addr_reg_index(ctx, t0);
6072
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6073 6074 6075 6076 6077 6078 6079 6080 6081 6082
    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);
    }
6083 6084 6085 6086
#endif
}

/* tlbwe */
B
Blue Swirl 已提交
6087
static void gen_tlbwe_440(DisasContext *ctx)
6088 6089
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6090
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6091
#else
A
aurel32 已提交
6092
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6093
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6094 6095 6096 6097 6098 6099
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6100 6101
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6102 6103
            gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
                                 cpu_gpr[rS(ctx->opcode)]);
6104 6105
            tcg_temp_free_i32(t0);
        }
6106 6107
        break;
    default:
A
aurel32 已提交
6108
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6109 6110 6111 6112 6113
        break;
    }
#endif
}

A
Alexander Graf 已提交
6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126
/* TLB management - PowerPC BookE 2.06 implementation */

/* tlbre */
static void gen_tlbre_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

6127
    gen_helper_booke206_tlbre(cpu_env);
A
Alexander Graf 已提交
6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150
#endif
}

/* tlbsx - tlbsx. */
static void gen_tlbsx_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    TCGv t0;
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

    if (rA(ctx->opcode)) {
        t0 = tcg_temp_new();
        tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
    } else {
        t0 = tcg_const_tl(0);
    }

    tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
6151
    gen_helper_booke206_tlbsx(cpu_env, t0);
A
Alexander Graf 已提交
6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164
#endif
}

/* tlbwe */
static void gen_tlbwe_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }
6165
    gen_update_nip(ctx, ctx->nip - 4);
6166
    gen_helper_booke206_tlbwe(cpu_env);
A
Alexander Graf 已提交
6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183
#endif
}

static void gen_tlbivax_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    TCGv t0;
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);

6184
    gen_helper_booke206_tlbivax(cpu_env, t0);
A
Alexander Graf 已提交
6185 6186 6187
#endif
}

A
Alexander Graf 已提交
6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203
static void gen_tlbilx_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    TCGv t0;
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);

    switch((ctx->opcode >> 21) & 0x3) {
    case 0:
6204
        gen_helper_booke206_tlbilx0(cpu_env, t0);
A
Alexander Graf 已提交
6205 6206
        break;
    case 1:
6207
        gen_helper_booke206_tlbilx1(cpu_env, t0);
A
Alexander Graf 已提交
6208 6209
        break;
    case 3:
6210
        gen_helper_booke206_tlbilx3(cpu_env, t0);
A
Alexander Graf 已提交
6211 6212 6213 6214 6215 6216 6217 6218 6219 6220
        break;
    default:
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        break;
    }

    tcg_temp_free(t0);
#endif
}

A
Alexander Graf 已提交
6221

6222
/* wrtee */
B
Blue Swirl 已提交
6223
static void gen_wrtee(DisasContext *ctx)
6224 6225
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6226
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6227
#else
6228
    TCGv t0;
A
aurel32 已提交
6229
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6230
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6231 6232
        return;
    }
6233 6234 6235 6236 6237
    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 已提交
6238 6239 6240
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
6241
    gen_stop_exception(ctx);
6242 6243 6244 6245
#endif
}

/* wrteei */
B
Blue Swirl 已提交
6246
static void gen_wrteei(DisasContext *ctx)
6247 6248
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6249
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6250
#else
A
aurel32 已提交
6251
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6252
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6253 6254
        return;
    }
6255
    if (ctx->opcode & 0x00008000) {
6256 6257
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6258
        gen_stop_exception(ctx);
6259
    } else {
A
aurel32 已提交
6260
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6261
    }
6262 6263 6264
#endif
}

J
j_mayer 已提交
6265
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
6266

6267
/* dlmzb */
B
Blue Swirl 已提交
6268
static void gen_dlmzb(DisasContext *ctx)
6269
{
6270
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6271 6272
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
6273
    tcg_temp_free_i32(t0);
6274 6275 6276
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
6277
static void gen_mbar(DisasContext *ctx)
6278 6279 6280 6281 6282
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
A
Alexander Graf 已提交
6283
static void gen_msync_4xx(DisasContext *ctx)
6284 6285 6286 6287 6288
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6289
static void gen_icbt_440(DisasContext *ctx)
6290 6291 6292 6293 6294
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6295 6296
}

A
Alexander Graf 已提交
6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308
/* Embedded.Processor Control */

static void gen_msgclr(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(ctx->mem_idx == 0)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

6309
    gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
A
Alexander Graf 已提交
6310 6311 6312
#endif
}

A
Alexander Graf 已提交
6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326
static void gen_msgsnd(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(ctx->mem_idx == 0)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }

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

6327 6328 6329
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

B
Blue Swirl 已提交
6330
static inline TCGv_ptr gen_avr_ptr(int reg)
A
aurel32 已提交
6331
{
A
aurel32 已提交
6332
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6333 6334 6335 6336
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

6337
#define GEN_VR_LDX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6338
static void glue(gen_, name)(DisasContext *ctx)                                       \
6339
{                                                                             \
6340
    TCGv EA;                                                                  \
6341
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6342
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6343 6344
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6345
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6346
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6347
    gen_addr_reg_index(ctx, EA);                                              \
6348
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6349 6350
    if (ctx->le_mode) {                                                       \
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6351
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6352
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6353
    } else {                                                                  \
A
aurel32 已提交
6354
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6355
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6356
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6357 6358
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6359 6360 6361
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6362
static void gen_st##name(DisasContext *ctx)                                   \
6363
{                                                                             \
6364
    TCGv EA;                                                                  \
6365
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6366
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6367 6368
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6369
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6370
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6371
    gen_addr_reg_index(ctx, EA);                                              \
6372
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6373 6374
    if (ctx->le_mode) {                                                       \
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6375
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6376
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6377
    } else {                                                                  \
A
aurel32 已提交
6378
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6379
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6380
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6381 6382
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6383 6384
}

A
aurel32 已提交
6385
#define GEN_VR_LVE(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6386
static void gen_lve##name(DisasContext *ctx)                            \
A
aurel32 已提交
6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397
    {                                                                   \
        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));                              \
6398
        gen_helper_lve##name(cpu_env, rs, EA);                          \
A
aurel32 已提交
6399 6400 6401 6402 6403
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

#define GEN_VR_STVE(name, opc2, opc3)                                   \
B
Blue Swirl 已提交
6404
static void gen_stve##name(DisasContext *ctx)                           \
A
aurel32 已提交
6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415
    {                                                                   \
        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));                              \
6416
        gen_helper_stve##name(cpu_env, rs, EA);                         \
A
aurel32 已提交
6417 6418 6419 6420
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

6421
GEN_VR_LDX(lvx, 0x07, 0x03);
6422
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6423
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6424

A
aurel32 已提交
6425 6426 6427 6428
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6429
GEN_VR_STX(svx, 0x07, 0x07);
6430
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6431
GEN_VR_STX(svxl, 0x07, 0x0F);
6432

A
aurel32 已提交
6433 6434 6435 6436
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

B
Blue Swirl 已提交
6437
static void gen_lvsl(DisasContext *ctx)
A
aurel32 已提交
6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452
{
    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 已提交
6453
static void gen_lvsr(DisasContext *ctx)
A
aurel32 已提交
6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468
{
    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 已提交
6469
static void gen_mfvscr(DisasContext *ctx)
6470 6471 6472 6473 6474 6475 6476 6477
{
    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();
6478
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
6479
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6480
    tcg_temp_free_i32(t);
6481 6482
}

B
Blue Swirl 已提交
6483
static void gen_mtvscr(DisasContext *ctx)
6484
{
A
aurel32 已提交
6485
    TCGv_ptr p;
6486 6487 6488 6489
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6490
    p = gen_avr_ptr(rD(ctx->opcode));
6491
    gen_helper_mtvscr(cpu_env, p);
A
aurel32 已提交
6492
    tcg_temp_free_ptr(p);
6493 6494
}

6495 6496
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
B
Blue Swirl 已提交
6497
static void glue(gen_, name)(DisasContext *ctx)                                 \
6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512
{                                                                       \
    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);

6513
#define GEN_VXFORM(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6514
static void glue(gen_, name)(DisasContext *ctx)                                 \
6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529
{                                                                       \
    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);                                              \
}

6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540
#define GEN_VXFORM_ENV(name, opc2, opc3)                                \
static void glue(gen_, name)(DisasContext *ctx)                         \
{                                                                       \
    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));                                  \
6541
    gen_helper_##name(cpu_env, rd, ra, rb);                             \
6542 6543 6544 6545 6546
    tcg_temp_free_ptr(ra);                                              \
    tcg_temp_free_ptr(rb);                                              \
    tcg_temp_free_ptr(rd);                                              \
}

A
aurel32 已提交
6547 6548 6549 6550 6551 6552
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);
6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564
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 已提交
6565 6566 6567 6568 6569 6570
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 已提交
6571 6572 6573 6574 6575 6576
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 已提交
6577 6578 6579 6580 6581 6582 6583 6584
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 已提交
6585 6586 6587
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6588 6589 6590 6591 6592 6593
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 已提交
6594 6595
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6596 6597
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609
GEN_VXFORM_ENV(vaddubs, 0, 8);
GEN_VXFORM_ENV(vadduhs, 0, 9);
GEN_VXFORM_ENV(vadduws, 0, 10);
GEN_VXFORM_ENV(vaddsbs, 0, 12);
GEN_VXFORM_ENV(vaddshs, 0, 13);
GEN_VXFORM_ENV(vaddsws, 0, 14);
GEN_VXFORM_ENV(vsububs, 0, 24);
GEN_VXFORM_ENV(vsubuhs, 0, 25);
GEN_VXFORM_ENV(vsubuws, 0, 26);
GEN_VXFORM_ENV(vsubsbs, 0, 28);
GEN_VXFORM_ENV(vsubshs, 0, 29);
GEN_VXFORM_ENV(vsubsws, 0, 30);
A
aurel32 已提交
6610 6611 6612
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6613 6614
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6615 6616 6617 6618 6619 6620 6621 6622
GEN_VXFORM_ENV(vpkuhum, 7, 0);
GEN_VXFORM_ENV(vpkuwum, 7, 1);
GEN_VXFORM_ENV(vpkuhus, 7, 2);
GEN_VXFORM_ENV(vpkuwus, 7, 3);
GEN_VXFORM_ENV(vpkshus, 7, 4);
GEN_VXFORM_ENV(vpkswus, 7, 5);
GEN_VXFORM_ENV(vpkshss, 7, 6);
GEN_VXFORM_ENV(vpkswss, 7, 7);
A
aurel32 已提交
6623
GEN_VXFORM(vpkpx, 7, 12);
6624 6625 6626 6627 6628 6629 6630 6631 6632
GEN_VXFORM_ENV(vsum4ubs, 4, 24);
GEN_VXFORM_ENV(vsum4sbs, 4, 28);
GEN_VXFORM_ENV(vsum4shs, 4, 25);
GEN_VXFORM_ENV(vsum2sws, 4, 26);
GEN_VXFORM_ENV(vsumsws, 4, 30);
GEN_VXFORM_ENV(vaddfp, 5, 0);
GEN_VXFORM_ENV(vsubfp, 5, 1);
GEN_VXFORM_ENV(vmaxfp, 5, 16);
GEN_VXFORM_ENV(vminfp, 5, 17);
A
aurel32 已提交
6633

6634
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
B
Blue Swirl 已提交
6635
static void glue(gen_, name)(DisasContext *ctx)                         \
6636 6637 6638 6639 6640 6641 6642 6643 6644
    {                                                                   \
        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));                              \
6645
        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
6646 6647 6648 6649 6650 6651 6652 6653 6654
        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)))

6655 6656 6657 6658 6659 6660 6661 6662 6663
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)
6664 6665 6666 6667
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6668

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

6689
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
B
Blue Swirl 已提交
6690
static void glue(gen_, name)(DisasContext *ctx)                                 \
6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703
    {                                                                   \
        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);                                         \
    }

6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719
#define GEN_VXFORM_NOA_ENV(name, opc2, opc3)                            \
static void glue(gen_, name)(DisasContext *ctx)                         \
    {                                                                   \
        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(cpu_env, rd, rb);                             \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6720 6721 6722 6723
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 已提交
6724 6725
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
6726 6727 6728 6729 6730 6731 6732 6733
GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
GEN_VXFORM_NOA_ENV(vrfim, 5, 8);
GEN_VXFORM_NOA_ENV(vrfin, 5, 9);
GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
GEN_VXFORM_NOA_ENV(vrfiz, 5, 11);
A
aurel32 已提交
6734

6735
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6736
static void glue(gen_, name)(DisasContext *ctx)                                 \
6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750
    {                                                                   \
        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);                                          \
    }

6751
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6752
static void glue(gen_, name)(DisasContext *ctx)                                 \
6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768
    {                                                                   \
        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);                                          \
    }

6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787
#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3)                           \
static void glue(gen_, name)(DisasContext *ctx)                         \
    {                                                                   \
        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(cpu_env, rd, rb, uimm);                       \
        tcg_temp_free_i32(uimm);                                        \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6788 6789 6790
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
6791 6792 6793 6794
GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
A
aurel32 已提交
6795

B
Blue Swirl 已提交
6796
static void gen_vsldoi(DisasContext *ctx)
A
aurel32 已提交
6797 6798
{
    TCGv_ptr ra, rb, rd;
6799
    TCGv_i32 sh;
A
aurel32 已提交
6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811
    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);
6812
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6813 6814
}

6815
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
6816
static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827
    {                                                                   \
        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)) {                                          \
6828
            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
6829
        } else {                                                        \
6830
            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
6831 6832 6833 6834 6835 6836 6837
        }                                                               \
        tcg_temp_free_ptr(ra);                                          \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rc);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6838 6839
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

B
Blue Swirl 已提交
6840
static void gen_vmladduhm(DisasContext *ctx)
A
aurel32 已提交
6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857
{
    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 已提交
6858
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6859
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6860
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6861
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6862
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6863

6864 6865
/***                           SPE extension                               ***/
/* Register moves */
6866

6867 6868 6869 6870 6871

static inline void gen_evmra(DisasContext *ctx)
{

    if (unlikely(!ctx->spe_enabled)) {
6872
        gen_exception(ctx, POWERPC_EXCP_SPEU);
6873 6874 6875 6876 6877 6878 6879 6880 6881 6882
        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,
6883
                   offsetof(CPUPPCState, spe_acc));
6884 6885 6886 6887 6888 6889 6890
#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 */
6891
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
6892 6893 6894 6895 6896 6897 6898 6899
    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 已提交
6900 6901
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
A
aurel32 已提交
6902 6903 6904
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
6905
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6906
#endif
A
aurel32 已提交
6907
}
6908

B
Blue Swirl 已提交
6909 6910
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
6911 6912 6913
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6914
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6915 6916 6917
    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 已提交
6918
    tcg_temp_free_i64(tmp);
6919
#endif
A
aurel32 已提交
6920
}
6921

6922
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type)         \
B
Blue Swirl 已提交
6923
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
6924 6925 6926 6927 6928 6929 6930 6931
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
6932
static inline void gen_speundef(DisasContext *ctx)
6933
{
A
aurel32 已提交
6934
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6935 6936
}

6937 6938 6939
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
6940
static inline void gen_##name(DisasContext *ctx)                              \
6941 6942
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6943
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6944 6945
        return;                                                               \
    }                                                                         \
6946 6947 6948 6949 6950
    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 已提交
6951
static inline void gen_##name(DisasContext *ctx)                              \
6952 6953
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6954
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
6955 6956 6957 6958 6959 6960
        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)]);                                        \
6961
}
6962 6963 6964 6965 6966 6967 6968 6969 6970 6971
#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);
6972

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

7014 7015 7016
/* SPE arithmetic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
7017
static inline void gen_##name(DisasContext *ctx)                              \
7018 7019
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7020
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7021 7022
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7023 7024 7025
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7026 7027 7028 7029
    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 已提交
7030
    tcg_temp_free_i64(t2);                                                    \
7031 7032
    tcg_op(t1, t1);                                                           \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7033 7034
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7035
}
7036
#else
P
pbrook 已提交
7037
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
7038
static inline void gen_##name(DisasContext *ctx)                              \
7039 7040
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7041
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7042 7043 7044 7045 7046 7047
        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
7048

B
Blue Swirl 已提交
7049
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
7050 7051 7052
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
7053

7054 7055 7056 7057
    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 已提交
7058
    tcg_gen_mov_i32(ret, arg1);
7059 7060 7061 7062 7063 7064
    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 已提交
7065
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
7066
{
7067 7068 7069 7070
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
7071 7072
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
7073

7074 7075
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
7076
static inline void gen_##name(DisasContext *ctx)                              \
7077 7078
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7079
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7080 7081
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7082 7083 7084
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
7085
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
7086 7087 7088 7089 7090 7091 7092
    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 已提交
7093
    tcg_temp_free_i64(t3);                                                    \
7094
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
7095
    tcg_temp_free_i32(t2);                                                    \
7096
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7097 7098
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7099
}
7100 7101
#else
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
7102
static inline void gen_##name(DisasContext *ctx)                              \
7103 7104
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7105
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7106 7107
        return;                                                               \
    }                                                                         \
7108 7109 7110 7111
    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)]);                                        \
7112
}
7113
#endif
7114

B
Blue Swirl 已提交
7115
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7116
{
P
pbrook 已提交
7117
    TCGv_i32 t0;
7118
    int l1, l2;
7119

7120 7121
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7122
    t0 = tcg_temp_local_new_i32();
7123 7124 7125 7126 7127 7128 7129
    /* 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);
7130
    gen_set_label(l2);
P
pbrook 已提交
7131
    tcg_temp_free_i32(t0);
7132 7133
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
7134
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7135
{
P
pbrook 已提交
7136
    TCGv_i32 t0;
7137 7138 7139 7140
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7141
    t0 = tcg_temp_local_new_i32();
7142 7143 7144 7145 7146 7147 7148
    /* 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);
7149
    gen_set_label(l2);
P
pbrook 已提交
7150
    tcg_temp_free_i32(t0);
7151 7152
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
7153
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7154
{
P
pbrook 已提交
7155
    TCGv_i32 t0;
7156 7157 7158 7159
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7160
    t0 = tcg_temp_local_new_i32();
7161 7162 7163 7164 7165 7166 7167
    /* 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);
7168
    gen_set_label(l2);
P
pbrook 已提交
7169
    tcg_temp_free_i32(t0);
7170 7171
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
B
Blue Swirl 已提交
7172
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7173
{
P
pbrook 已提交
7174
    TCGv_i32 t0 = tcg_temp_new_i32();
7175 7176
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
7177
    tcg_temp_free_i32(t0);
7178 7179
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
B
Blue Swirl 已提交
7180
static inline void gen_evmergehi(DisasContext *ctx)
7181 7182
{
    if (unlikely(!ctx->spe_enabled)) {
7183
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7184 7185 7186
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7187 7188
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199
    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 已提交
7200
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7201
{
7202 7203 7204
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
7205

7206 7207 7208
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7209
static inline void gen_##name(DisasContext *ctx)                              \
7210 7211
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7212
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7213 7214
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7215 7216 7217
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7218 7219 7220 7221
    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 已提交
7222
    tcg_temp_free_i64(t2);                                                    \
7223 7224
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7225 7226
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7227 7228 7229
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7230
static inline void gen_##name(DisasContext *ctx)                              \
7231 7232
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7233
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247
        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 已提交
7248
static inline void gen_##name(DisasContext *ctx)                              \
7249 7250
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7251
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7252 7253 7254 7255 7256 7257
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
7258 7259 7260
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7261 7262 7263
    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 已提交
7264
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
7265 7266 7267 7268 7269 7270 7271 7272 7273
    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 已提交
7274
    tcg_temp_free_i64(t2);                                                    \
7275 7276 7277 7278 7279 7280 7281 7282
    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 已提交
7283 7284
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7285 7286 7287
}
#else
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
B
Blue Swirl 已提交
7288
static inline void gen_##name(DisasContext *ctx)                              \
7289 7290
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7291
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324
        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 已提交
7325
static inline void gen_brinc(DisasContext *ctx)
7326 7327
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
7328 7329
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7330
}
B
Blue Swirl 已提交
7331
static inline void gen_evmergelo(DisasContext *ctx)
7332 7333
{
    if (unlikely(!ctx->spe_enabled)) {
7334
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7335 7336 7337
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7338 7339
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7340
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7341 7342 7343 7344 7345 7346
    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)]);
7347
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7348 7349
#endif
}
B
Blue Swirl 已提交
7350
static inline void gen_evmergehilo(DisasContext *ctx)
7351 7352
{
    if (unlikely(!ctx->spe_enabled)) {
7353
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7354 7355 7356
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7357 7358
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7359
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7360 7361 7362 7363 7364 7365 7366 7367 7368
    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 已提交
7369
static inline void gen_evmergelohi(DisasContext *ctx)
7370 7371
{
    if (unlikely(!ctx->spe_enabled)) {
7372
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7373 7374 7375
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7376 7377
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7378 7379 7380 7381 7382 7383
    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
7384 7385 7386 7387 7388 7389 7390 7391 7392 7393
    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)]);
    }
7394 7395
#endif
}
B
Blue Swirl 已提交
7396
static inline void gen_evsplati(DisasContext *ctx)
7397
{
7398
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
7399

7400
#if defined(TARGET_PPC64)
7401
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7402 7403 7404 7405 7406
#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 已提交
7407
static inline void gen_evsplatfi(DisasContext *ctx)
7408
{
7409
    uint64_t imm = rA(ctx->opcode) << 27;
7410

7411
#if defined(TARGET_PPC64)
7412
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7413 7414 7415 7416
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7417 7418
}

B
Blue Swirl 已提交
7419
static inline void gen_evsel(DisasContext *ctx)
7420 7421 7422 7423 7424
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7425
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7426
#if defined(TARGET_PPC64)
P
pbrook 已提交
7427 7428
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447
#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)
7448
    tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
7449 7450 7451 7452 7453 7454
#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)
7455
    tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
7456 7457 7458 7459
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7460
    tcg_temp_free_i32(t0);
7461 7462 7463 7464 7465 7466
#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 已提交
7467 7468

static void gen_evsel0(DisasContext *ctx)
7469 7470 7471
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7472 7473

static void gen_evsel1(DisasContext *ctx)
7474 7475 7476
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7477 7478

static void gen_evsel2(DisasContext *ctx)
7479 7480 7481
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7482 7483

static void gen_evsel3(DisasContext *ctx)
7484 7485 7486
{
    gen_evsel(ctx);
}
7487

7488 7489 7490 7491 7492 7493 7494
/* Multiply */

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

    if (unlikely(!ctx->spe_enabled)) {
7495
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523
        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)) {
7524
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7525 7526 7527 7528 7529 7530 7531 7532 7533
        return;
    }

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

    tmp = tcg_temp_new_i64();

    /* acc := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));
7534
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7535 7536 7537 7538 7539 7540 7541 7542 7543
    tcg_temp_free_i64(tmp);
}

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

    if (unlikely(!ctx->spe_enabled)) {
7544
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556
        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 */
7557
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7558 7559 7560 7561 7562

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

    /* Store acc */
7563
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576

    /* 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)) {
7577
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610
        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));
7611
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629

    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 */
7630
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7631 7632 7633 7634 7635

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

    /* Store acc */
7636
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7637 7638 7639 7640 7641 7642 7643 7644

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

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673
GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE); //
GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE);
GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE); //
GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE); ////
7674

7675
/* SPE load and stores */
B
Blue Swirl 已提交
7676
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7677 7678 7679
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7680
    if (rA(ctx->opcode) == 0) {
7681
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7682
    } else {
7683
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
A
aurel32 已提交
7684 7685 7686 7687 7688 7689
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
7690
}
7691

B
Blue Swirl 已提交
7692
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7693 7694
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7695
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7696 7697
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7698
    gen_qemu_ld64(ctx, t0, addr);
7699 7700 7701 7702 7703
    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
7704
}
7705

B
Blue Swirl 已提交
7706
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7707
{
7708
#if defined(TARGET_PPC64)
7709
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7710
    gen_qemu_ld32u(ctx, t0, addr);
7711
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7712 7713
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7714 7715 7716
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7717 7718 7719
    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);
7720
#endif
7721
}
7722

B
Blue Swirl 已提交
7723
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7724 7725 7726
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7727
    gen_qemu_ld16u(ctx, t0, addr);
7728
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7729 7730
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7731 7732
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7733 7734
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7735 7736
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7737 7738
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7739
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7740
#else
A
aurel32 已提交
7741
    gen_qemu_ld16u(ctx, t0, addr);
7742
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7743 7744
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7745
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7746 7747
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7748
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7749 7750
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7751
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7752
#endif
7753
    tcg_temp_free(t0);
7754 7755
}

B
Blue Swirl 已提交
7756
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7757 7758
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7759
    gen_qemu_ld16u(ctx, t0, addr);
7760 7761 7762 7763 7764 7765 7766 7767 7768 7769
#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);
7770 7771
}

B
Blue Swirl 已提交
7772
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7773 7774
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7775
    gen_qemu_ld16u(ctx, t0, addr);
7776 7777 7778 7779 7780 7781 7782 7783
#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);
7784 7785
}

B
Blue Swirl 已提交
7786
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7787 7788
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7789
    gen_qemu_ld16s(ctx, t0, addr);
7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800
#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 已提交
7801
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7802 7803 7804
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7805
    gen_qemu_ld16u(ctx, t0, addr);
7806
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7807 7808
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7809 7810 7811
    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 已提交
7812
    gen_qemu_ld16u(ctx, t0, addr);
7813
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7814 7815
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7816 7817 7818 7819 7820
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7821
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7822 7823 7824
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7825 7826 7827
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7828 7829 7830 7831
    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 已提交
7832 7833 7834
    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);
7835 7836 7837
#endif
}

B
Blue Swirl 已提交
7838
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7839 7840 7841
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7842
    gen_qemu_ld16s(ctx, t0, addr);
7843
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7844 7845
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7846 7847 7848 7849
    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 已提交
7850 7851 7852
    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);
7853 7854 7855
#endif
}

B
Blue Swirl 已提交
7856
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7857 7858
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7859
    gen_qemu_ld32u(ctx, t0, addr);
7860
#if defined(TARGET_PPC64)
7861 7862 7863 7864 7865 7866 7867 7868 7869
    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 已提交
7870
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7871 7872 7873
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7874
    gen_qemu_ld16u(ctx, t0, addr);
7875 7876 7877
    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 已提交
7878 7879
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7880 7881 7882 7883
    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 已提交
7884
    gen_qemu_ld16u(ctx, t0, addr);
7885 7886
    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 已提交
7887 7888
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7889 7890
    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);
7891
#endif
7892 7893 7894
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7895
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7896 7897
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7898
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7899
#else
7900 7901
    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 已提交
7902
    gen_qemu_st64(ctx, t0, addr);
7903 7904 7905 7906
    tcg_temp_free_i64(t0);
#endif
}

B
Blue Swirl 已提交
7907
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7908
{
7909
#if defined(TARGET_PPC64)
7910 7911
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7912
    gen_qemu_st32(ctx, t0, addr);
7913 7914
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7915
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7916
#endif
A
aurel32 已提交
7917 7918
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7919 7920
}

B
Blue Swirl 已提交
7921
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7922 7923 7924 7925 7926 7927 7928
{
    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 已提交
7929 7930
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7931 7932
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7933
    gen_qemu_st16(ctx, t0, addr);
7934
#else
A
aurel32 已提交
7935
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7936
#endif
A
aurel32 已提交
7937
    gen_addr_add(ctx, addr, addr, 2);
7938
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7939
    gen_qemu_st16(ctx, t0, addr);
7940
    tcg_temp_free(t0);
A
aurel32 已提交
7941 7942
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7943 7944
}

B
Blue Swirl 已提交
7945
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7946 7947 7948 7949 7950 7951 7952
{
    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 已提交
7953 7954
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7955
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7956
    gen_qemu_st16(ctx, t0, addr);
7957 7958 7959
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7960
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7961 7962 7963 7964
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7965
    gen_qemu_st16(ctx, t0, addr);
7966 7967
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7968
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7969
#endif
A
aurel32 已提交
7970 7971
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7972 7973
}

B
Blue Swirl 已提交
7974
static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7975 7976 7977 7978
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7979
    gen_qemu_st32(ctx, t0, addr);
7980 7981
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7982
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7983 7984 7985
#endif
}

B
Blue Swirl 已提交
7986
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7987
{
A
aurel32 已提交
7988
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7989 7990 7991
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
B
Blue Swirl 已提交
7992
static void glue(gen_, name)(DisasContext *ctx)                                       \
7993 7994 7995
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7996
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7997 7998
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7999
    gen_set_access_type(ctx, ACCESS_INT);                                     \
8000 8001
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
8002
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
8003
    } else {                                                                  \
A
aurel32 已提交
8004
        gen_addr_reg_index(ctx, t0);                                          \
8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028
    }                                                                         \
    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);
8029 8030 8031

/* Multiply and add - TODO */
#if 0
8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099
GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);//
GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);

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

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

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

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

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

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

/***                      SPE floating-point extension                     ***/
A
aurel32 已提交
8103 8104
#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
8105
static inline void gen_##name(DisasContext *ctx)                              \
8106
{                                                                             \
A
aurel32 已提交
8107 8108 8109 8110
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8111
    gen_helper_##name(t0, cpu_env, t0);                                       \
A
aurel32 已提交
8112 8113 8114 8115 8116 8117 8118
    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);                                                        \
8119
}
A
aurel32 已提交
8120
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
8121
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8122 8123 8124 8125
{                                                                             \
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
8126
    gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]);                 \
A
aurel32 已提交
8127 8128 8129 8130 8131 8132 8133 8134 8135
    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 已提交
8136
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8137 8138 8139
{                                                                             \
    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8140
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);                 \
A
aurel32 已提交
8141 8142 8143
    tcg_temp_free_i32(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
B
Blue Swirl 已提交
8144
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8145
{                                                                             \
8146 8147
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rB(ctx->opcode)]);                              \
A
aurel32 已提交
8148 8149
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
8150
static inline void gen_##name(DisasContext *ctx)                              \
8151
{                                                                             \
A
aurel32 已提交
8152 8153
    TCGv_i32 t0, t1;                                                          \
    TCGv_i64 t2;                                                              \
8154
    if (unlikely(!ctx->spe_enabled)) {                                        \
8155
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8156 8157
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8158 8159 8160 8161
    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)]);                       \
8162
    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
A
aurel32 已提交
8163 8164 8165 8166 8167 8168 8169 8170
    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);                                                        \
8171
}
A
aurel32 已提交
8172
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
8173
static inline void gen_##name(DisasContext *ctx)                              \
8174 8175
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8176
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8177 8178
        return;                                                               \
    }                                                                         \
8179 8180
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
8181
}
A
aurel32 已提交
8182
#define GEN_SPEFPUOP_COMP_32(name)                                            \
B
Blue Swirl 已提交
8183
static inline void gen_##name(DisasContext *ctx)                              \
8184
{                                                                             \
A
aurel32 已提交
8185
    TCGv_i32 t0, t1;                                                          \
8186
    if (unlikely(!ctx->spe_enabled)) {                                        \
8187
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8188 8189
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8190 8191 8192 8193
    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)]);                       \
8194
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
A
aurel32 已提交
8195 8196 8197 8198
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
B
Blue Swirl 已提交
8199
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8200 8201
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8202
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8203 8204
        return;                                                               \
    }                                                                         \
8205
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env,                    \
A
aurel32 已提交
8206 8207 8208 8209
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#else
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
8210
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8211
{                                                                             \
8212 8213
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rB(ctx->opcode)]);                              \
8214
}
A
aurel32 已提交
8215
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
8216
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8217 8218 8219
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
8220
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);                 \
A
aurel32 已提交
8221 8222 8223
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
B
Blue Swirl 已提交
8224
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8225 8226
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
8227
    gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]);                 \
A
aurel32 已提交
8228 8229 8230 8231
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
B
Blue Swirl 已提交
8232
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8233 8234 8235
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
8236
    gen_helper_##name(t0, cpu_env, t0);                                       \
A
aurel32 已提交
8237 8238 8239 8240
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
8241
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8242 8243
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8244
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8245 8246
        return;                                                               \
    }                                                                         \
8247
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
A
aurel32 已提交
8248 8249 8250
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
8251
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8252 8253 8254
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8255
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8256 8257 8258 8259 8260 8261
        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));                                      \
8262
    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
A
aurel32 已提交
8263 8264 8265 8266 8267
    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 已提交
8268
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8269 8270
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8271
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8272 8273
        return;                                                               \
    }                                                                         \
8274
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env,                    \
A
aurel32 已提交
8275 8276 8277
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
B
Blue Swirl 已提交
8278
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8279 8280 8281
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8282
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8283 8284 8285 8286 8287 8288
        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));                                      \
8289
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
A
aurel32 已提交
8290 8291 8292 8293
    tcg_temp_free_i64(t0);                                                    \
    tcg_temp_free_i64(t1);                                                    \
}
#endif
8294

8295 8296
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
8297 8298 8299 8300
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 已提交
8301
static inline void gen_evfsabs(DisasContext *ctx)
A
aurel32 已提交
8302 8303
{
    if (unlikely(!ctx->spe_enabled)) {
8304
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8305 8306 8307
        return;
    }
#if defined(TARGET_PPC64)
8308
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
A
aurel32 已提交
8309
#else
8310 8311
    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 已提交
8312 8313
#endif
}
B
Blue Swirl 已提交
8314
static inline void gen_evfsnabs(DisasContext *ctx)
A
aurel32 已提交
8315 8316
{
    if (unlikely(!ctx->spe_enabled)) {
8317
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8318 8319 8320
        return;
    }
#if defined(TARGET_PPC64)
8321
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8322
#else
8323 8324
    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 已提交
8325 8326
#endif
}
B
Blue Swirl 已提交
8327
static inline void gen_evfsneg(DisasContext *ctx)
A
aurel32 已提交
8328 8329
{
    if (unlikely(!ctx->spe_enabled)) {
8330
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8331 8332 8333
        return;
    }
#if defined(TARGET_PPC64)
8334
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8335
#else
8336 8337
    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 已提交
8338 8339 8340
#endif
}

8341
/* Conversion */
A
aurel32 已提交
8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352
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);

8353
/* Comparison */
A
aurel32 已提交
8354 8355 8356 8357 8358 8359
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);
8360 8361

/* Opcodes definitions */
8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375
GEN_SPE(evfsadd,   evfssub,   0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(evfsabs,   evfsnabs,  0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(evfsneg,   speundef,  0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(evfsmul,   evfsdiv,   0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfscmpeq, speundef,  0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(evfscfui,  evfscfsi,  0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfscfuf,  evfscfsf,  0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctui,  evfsctsi,  0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctuf,  evfsctsf,  0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctuiz, speundef,  0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(evfsctsiz, speundef,  0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfststeq, speundef,  0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8376 8377 8378

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8379 8380 8381 8382
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 已提交
8383
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
8384 8385
{
    if (unlikely(!ctx->spe_enabled)) {
8386
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8387 8388
        return;
    }
8389
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
A
aurel32 已提交
8390
}
B
Blue Swirl 已提交
8391
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
8392 8393
{
    if (unlikely(!ctx->spe_enabled)) {
8394
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8395 8396
        return;
    }
8397
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8398
}
B
Blue Swirl 已提交
8399
static inline void gen_efsneg(DisasContext *ctx)
A
aurel32 已提交
8400 8401
{
    if (unlikely(!ctx->spe_enabled)) {
8402
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8403 8404
        return;
    }
8405
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8406 8407
}

8408
/* Conversion */
A
aurel32 已提交
8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420
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);

8421
/* Comparison */
A
aurel32 已提交
8422 8423 8424 8425 8426 8427
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);
8428 8429

/* Opcodes definitions */
8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443
GEN_SPE(efsadd,   efssub,   0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(efsabs,   efsnabs,  0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(efsneg,   speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(efsmul,   efsdiv,   0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efscmpeq, efscfd,   0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efscfui,  efscfsi,  0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efscfuf,  efscfsf,  0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctui,  efsctsi,  0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctuf,  efsctsf,  0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8444 8445 8446

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8447 8448 8449 8450
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 已提交
8451
static inline void gen_efdabs(DisasContext *ctx)
A
aurel32 已提交
8452 8453
{
    if (unlikely(!ctx->spe_enabled)) {
8454
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8455 8456 8457
        return;
    }
#if defined(TARGET_PPC64)
8458
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
A
aurel32 已提交
8459
#else
8460 8461
    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 已提交
8462 8463
#endif
}
B
Blue Swirl 已提交
8464
static inline void gen_efdnabs(DisasContext *ctx)
A
aurel32 已提交
8465 8466
{
    if (unlikely(!ctx->spe_enabled)) {
8467
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8468 8469 8470
        return;
    }
#if defined(TARGET_PPC64)
8471
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8472
#else
8473 8474
    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 已提交
8475 8476
#endif
}
B
Blue Swirl 已提交
8477
static inline void gen_efdneg(DisasContext *ctx)
A
aurel32 已提交
8478 8479
{
    if (unlikely(!ctx->spe_enabled)) {
8480
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8481 8482 8483
        return;
    }
#if defined(TARGET_PPC64)
8484
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8485
#else
8486 8487
    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 已提交
8488 8489 8490
#endif
}

8491
/* Conversion */
A
aurel32 已提交
8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506
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);
8507 8508

/* Comparison */
A
aurel32 已提交
8509 8510 8511 8512 8513 8514
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);
8515 8516

/* Opcodes definitions */
8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532
GEN_SPE(efdadd,    efdsub,    0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfuid,  efdcfsid,  0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdabs,    efdnabs,   0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE); //
GEN_SPE(efdneg,    speundef,  0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
GEN_SPE(efdmul,    efddiv,    0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcmpgt,  efdcmplt,  0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcmpeq,  efdcfs,    0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfui,   efdcfsi,   0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfuf,   efdcfsf,   0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctui,   efdctsi,   0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuf,   efdctsf,   0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuiz,  speundef,  0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
GEN_SPE(efdctsiz,  speundef,  0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
GEN_SPE(efdtstgt,  efdtstlt,  0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdtsteq,  speundef,  0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
8533

A
Anthony Liguori 已提交
8534
static opcode_t opcodes[] = {
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
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),
8566
GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
8567
#if defined(TARGET_PPC64)
8568
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
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
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),
8610
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
8611 8612
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
8613
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
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
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),
8669 8670 8671
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),
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
#endif
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE),
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
#if defined(TARGET_PPC64)
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
#endif
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
A
Alexander Graf 已提交
8752
GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
8753 8754 8755 8756 8757 8758 8759 8760
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
A
Alexander Graf 已提交
8761 8762 8763 8764 8765 8766 8767 8768
GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
               PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
               PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
               PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8769 8770
GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8771 8772
GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
A
Alexander Graf 已提交
8773 8774
GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
8775
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8776
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8777
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
A
Alexander Graf 已提交
8778 8779
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
              PPC_BOOKE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8780
GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
A
Alexander Graf 已提交
8781 8782
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
               PPC_BOOKE, PPC2_BOOKE206),
8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954
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
8955
#undef GEN_LDX_E
8956 8957 8958 8959 8960 8961 8962
#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),
8963 8964
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979
#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)
8980
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
8981 8982 8983 8984 8985 8986 8987
#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
8988
#undef GEN_STX_E
8989 8990 8991 8992 8993 8994 8995
#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),
8996 8997
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009
#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)
9010
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278
#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),
9279
GEN_VXFORM_NOA(vexptefp, 5, 6),
9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307
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
9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
    GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
GEN_SPE(evaddw,      speundef,    0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evaddiw,     speundef,    0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evsubfw,     speundef,    0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evsubifw,    speundef,    0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evabs,       evneg,       0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
GEN_SPE(evextsb,     evextsh,     0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
GEN_SPE(evrndw,      evcntlzw,    0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
GEN_SPE(evcntlsw,    brinc,       0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE),
GEN_SPE(evmra,       speundef,    0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(speundef,    evand,       0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
GEN_SPE(evandc,      speundef,    0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evxor,       evor,        0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evnor,       eveqv,       0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evmwumi,     evmwsmi,     0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evmwumia,    evmwsmia,    0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evmwumiaa,   evmwsmiaa,   0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(speundef,    evorc,       0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
GEN_SPE(evnand,      speundef,    0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evsrwu,      evsrws,      0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evsrwiu,     evsrwis,     0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evslw,       speundef,    0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evslwi,      speundef,    0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
GEN_SPE(evrlw,       evsplati,    0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
GEN_SPE(evrlwi,      evsplatfi,   0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
GEN_SPE(evmergehi,   evmergelo,   0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE),
GEN_SPE(evcmpgtu,    evcmpgts,    0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE),
GEN_SPE(evcmpltu,    evcmplts,    0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE),
GEN_SPE(evcmpeq,     speundef,    0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE),

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

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

GEN_SPE(efdadd,      efdsub,      0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
GEN_SPE(efdcfuid,    efdcfsid,    0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdabs,      efdnabs,     0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE),
GEN_SPE(efdneg,      speundef,    0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE),
GEN_SPE(efdmul,      efddiv,      0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
GEN_SPE(efdctuidz,   efdctsidz,   0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdcmpgt,    efdcmplt,    0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
GEN_SPE(efdcmpeq,    efdcfs,      0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdcfui,     efdcfsi,     0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdcfuf,     efdcfsf,     0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctui,     efdctsi,     0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctuf,     efdctsf,     0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
GEN_SPE(efdctuiz,    speundef,    0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
GEN_SPE(efdctsiz,    speundef,    0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
GEN_SPE(efdtstgt,    efdtstlt,    0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
GEN_SPE(efdtsteq,    speundef,    0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410

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

9411
#include "helper_regs.h"
A
Andreas Färber 已提交
9412
#include "translate_init.c"
B
bellard 已提交
9413

9414
/*****************************************************************************/
9415
/* Misc PowerPC helpers */
9416
void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
9417
                     int flags)
B
bellard 已提交
9418
{
9419 9420 9421
#define RGPL  4
#define RFPL  4

B
bellard 已提交
9422 9423
    int i;

9424 9425
    cpu_synchronize_state(env);

9426
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
9427 9428
                TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
                env->nip, env->lr, env->ctr, env->xer);
9429 9430 9431
    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);
9432
#if !defined(NO_TIMER_DUMP)
9433
    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
9434
#if !defined(CONFIG_USER_ONLY)
9435
                " DECR %08" PRIu32
9436 9437
#endif
                "\n",
J
j_mayer 已提交
9438
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
9439 9440 9441 9442
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
9443
#endif
9444
    for (i = 0; i < 32; i++) {
9445 9446
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
9447
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
9448
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
9449
            cpu_fprintf(f, "\n");
9450
    }
9451
    cpu_fprintf(f, "CR ");
9452
    for (i = 0; i < 8; i++)
B
bellard 已提交
9453 9454
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
9455 9456 9457 9458 9459 9460 9461 9462
    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 已提交
9463
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
9464
    }
9465 9466
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
9467 9468 9469
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
9470
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
9471
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
9472
            cpu_fprintf(f, "\n");
B
bellard 已提交
9473
    }
9474
    cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
9475
#if !defined(CONFIG_USER_ONLY)
S
Scott Wood 已提交
9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523
    cpu_fprintf(f, " SRR0 " TARGET_FMT_lx "  SRR1 " TARGET_FMT_lx
                   "    PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
                env->spr[SPR_SRR0], env->spr[SPR_SRR1],
                env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);

    cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
                   "  SPRG2 " TARGET_FMT_lx "  SPRG3 " TARGET_FMT_lx "\n",
                env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
                env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);

    cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
                   "  SPRG6 " TARGET_FMT_lx "  SPRG7 " TARGET_FMT_lx "\n",
                env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
                env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);

    if (env->excp_model == POWERPC_EXCP_BOOKE) {
        cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
                       " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
                    env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);

        cpu_fprintf(f, "  TCR " TARGET_FMT_lx "   TSR " TARGET_FMT_lx
                       "    ESR " TARGET_FMT_lx "   DEAR " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
                    env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);

        cpu_fprintf(f, "  PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
                       "   IVPR " TARGET_FMT_lx "   EPCR " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
                    env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);

        cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
                       "    EPR " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
                    env->spr[SPR_BOOKE_EPR]);

        /* FSL-specific */
        cpu_fprintf(f, " MCAR " TARGET_FMT_lx "  PID1 " TARGET_FMT_lx
                       "   PID2 " TARGET_FMT_lx "    SVR " TARGET_FMT_lx "\n",
                    env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
                    env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);

        /*
         * IVORs are left out as they are large and do not change often --
         * they can be read with "p $ivor0", "p $ivor1", etc.
         */
    }

D
David Gibson 已提交
9524 9525 9526 9527 9528 9529
#if defined(TARGET_PPC64)
    if (env->flags & POWERPC_FLAG_CFAR) {
        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
    }
#endif

S
Scott Wood 已提交
9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540
    switch (env->mmu_model) {
    case POWERPC_MMU_32B:
    case POWERPC_MMU_601:
    case POWERPC_MMU_SOFT_6xx:
    case POWERPC_MMU_SOFT_74xx:
#if defined(TARGET_PPC64)
    case POWERPC_MMU_620:
    case POWERPC_MMU_64B:
#endif
        cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
        break;
A
Alexander Graf 已提交
9541
    case POWERPC_MMU_BOOKE206:
S
Scott Wood 已提交
9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559
        cpu_fprintf(f, " MAS0 " TARGET_FMT_lx "  MAS1 " TARGET_FMT_lx
                       "   MAS2 " TARGET_FMT_lx "   MAS3 " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
                    env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);

        cpu_fprintf(f, " MAS4 " TARGET_FMT_lx "  MAS6 " TARGET_FMT_lx
                       "   MAS7 " TARGET_FMT_lx "    PID " TARGET_FMT_lx "\n",
                    env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
                    env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);

        cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
                       " TLB1CFG " TARGET_FMT_lx "\n",
                    env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
                    env->spr[SPR_BOOKE_TLB1CFG]);
        break;
    default:
        break;
    }
9560
#endif
B
bellard 已提交
9561

9562 9563
#undef RGPL
#undef RFPL
B
bellard 已提交
9564 9565
}

9566
void cpu_dump_statistics (CPUPPCState *env, FILE*f, fprintf_function cpu_fprintf,
9567 9568 9569
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
A
Anthony Liguori 已提交
9570
    opc_handler_t **t1, **t2, **t3, *handler;
9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586
    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 已提交
9587
                                    "%016" PRIx64 " %" PRId64 "\n",
9588 9589 9590 9591 9592 9593 9594 9595
                                    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 已提交
9596
                                "%016" PRIx64 " %" PRId64 "\n",
9597 9598 9599 9600 9601 9602 9603
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
B
Blue Swirl 已提交
9604 9605
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
                        " %" PRId64 "\n",
9606 9607 9608 9609 9610 9611 9612
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

9613
/*****************************************************************************/
9614
static inline void gen_intermediate_code_internal(CPUPPCState *env,
B
Blue Swirl 已提交
9615 9616
                                                  TranslationBlock *tb,
                                                  int search_pc)
B
bellard 已提交
9617
{
9618
    DisasContext ctx, *ctxp = &ctx;
A
Anthony Liguori 已提交
9619
    opc_handler_t **table, *handler;
B
bellard 已提交
9620
    target_ulong pc_start;
B
bellard 已提交
9621
    uint16_t *gen_opc_end;
9622
    CPUBreakpoint *bp;
B
bellard 已提交
9623
    int j, lj = -1;
P
pbrook 已提交
9624 9625
    int num_insns;
    int max_insns;
B
bellard 已提交
9626 9627

    pc_start = tb->pc;
9628
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
9629
    ctx.nip = pc_start;
B
bellard 已提交
9630
    ctx.tb = tb;
9631
    ctx.exception = POWERPC_EXCP_NONE;
9632
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
9633 9634 9635
    ctx.mem_idx = env->mmu_idx;
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
9636
#if defined(TARGET_PPC64)
A
Alexander Graf 已提交
9637
    ctx.sf_mode = msr_is_64bit(env, env->msr);
D
David Gibson 已提交
9638
    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9639
#endif
B
bellard 已提交
9640
    ctx.fpu_enabled = msr_fp;
9641
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
9642 9643 9644
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
9645 9646 9647 9648
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
9649
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
9650
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
9651
    else
9652
        ctx.singlestep_enabled = 0;
9653
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
9654 9655 9656
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
9657
#if defined (DO_SINGLE_STEP) && 0
9658 9659 9660
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
9661 9662 9663 9664 9665 9666
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
9667
    /* Set env in case of segfault during code fetch */
9668 9669
    while (ctx.exception == POWERPC_EXCP_NONE
            && tcg_ctx.gen_opc_ptr < gen_opc_end) {
B
Blue Swirl 已提交
9670 9671
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9672
                if (bp->pc == ctx.nip) {
A
aurel32 已提交
9673
                    gen_debug_exception(ctxp);
9674 9675 9676 9677
                    break;
                }
            }
        }
9678
        if (unlikely(search_pc)) {
9679
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
B
bellard 已提交
9680 9681 9682
            if (lj < j) {
                lj++;
                while (lj < j)
9683
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
9684
            }
9685
            tcg_ctx.gen_opc_pc[lj] = ctx.nip;
9686
            tcg_ctx.gen_opc_instr_start[lj] = 1;
9687
            tcg_ctx.gen_opc_icount[lj] = num_insns;
B
bellard 已提交
9688
        }
9689
        LOG_DISAS("----------------\n");
9690
        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
9691
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
P
pbrook 已提交
9692 9693
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
A
aurel32 已提交
9694
        if (unlikely(ctx.le_mode)) {
9695
            ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
9696
        } else {
9697
            ctx.opcode = cpu_ldl_code(env, ctx.nip);
9698
        }
9699
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9700
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
9701
                    opc3(ctx.opcode), little_endian ? "little" : "big");
9702
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
9703
            tcg_gen_debug_insn_start(ctx.nip);
9704
        }
B
bellard 已提交
9705
        ctx.nip += 4;
9706
        table = env->opcodes;
P
pbrook 已提交
9707
        num_insns++;
B
bellard 已提交
9708 9709 9710 9711 9712 9713 9714 9715 9716 9717
        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 ? */
9718
        if (unlikely(handler->handler == &gen_invalid)) {
9719 9720
            if (qemu_log_enabled()) {
                qemu_log("invalid/unsupported opcode: "
9721 9722 9723
                         "%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 已提交
9724
            }
9725
        } else {
9726 9727 9728 9729 9730 9731 9732 9733 9734
            uint32_t inval;

            if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE) && Rc(ctx.opcode))) {
                inval = handler->inval2;
            } else {
                inval = handler->inval1;
            }

            if (unlikely((ctx.opcode & inval) != 0)) {
9735 9736
                if (qemu_log_enabled()) {
                    qemu_log("invalid bits: %08x for opcode: "
9737
                             "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
9738
                             ctx.opcode & inval, opc1(ctx.opcode),
9739 9740
                             opc2(ctx.opcode), opc3(ctx.opcode),
                             ctx.opcode, ctx.nip - 4);
9741
                }
A
aurel32 已提交
9742
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
B
bellard 已提交
9743
                break;
B
bellard 已提交
9744 9745
            }
        }
B
bellard 已提交
9746
        (*(handler->handler))(&ctx);
9747 9748 9749
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
9750
        /* Check trace mode exceptions */
9751 9752 9753 9754 9755
        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 已提交
9756
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
9757
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
9758
                            (env->singlestep_enabled) ||
9759
                            singlestep ||
P
pbrook 已提交
9760
                            num_insns >= max_insns)) {
9761 9762 9763
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
9764
            break;
9765
        }
9766
    }
P
pbrook 已提交
9767 9768
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
9769
    if (ctx.exception == POWERPC_EXCP_NONE) {
9770
        gen_goto_tb(&ctx, 0, ctx.nip);
9771
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
9772
        if (unlikely(env->singlestep_enabled)) {
A
aurel32 已提交
9773
            gen_debug_exception(ctxp);
9774
        }
9775
        /* Generate the return instruction */
B
bellard 已提交
9776
        tcg_gen_exit_tb(0);
9777
    }
P
pbrook 已提交
9778
    gen_icount_end(tb, num_insns);
9779
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
9780
    if (unlikely(search_pc)) {
9781
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
9782 9783
        lj++;
        while (lj <= j)
9784
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
9785
    } else {
B
bellard 已提交
9786
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
9787
        tb->icount = num_insns;
9788
    }
9789
#if defined(DEBUG_DISAS)
9790
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9791
        int flags;
9792
        flags = env->bfd_mach;
A
aurel32 已提交
9793
        flags |= ctx.le_mode << 16;
9794
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
B
Blue Swirl 已提交
9795
        log_target_disas(env, pc_start, ctx.nip - pc_start, flags);
9796
        qemu_log("\n");
9797
    }
B
bellard 已提交
9798 9799 9800
#endif
}

9801
void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9802
{
9803
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
9804 9805
}

9806
void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9807
{
9808
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
9809
}
A
aurel32 已提交
9810

9811
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
A
aurel32 已提交
9812
{
9813
    env->nip = tcg_ctx.gen_opc_pc[pc_pos];
A
aurel32 已提交
9814
}