translate.c 364.3 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
69
static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca;
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");
161 162 163 164 165 166
    cpu_so = tcg_global_mem_new(TCG_AREG0,
                                offsetof(CPUPPCState, so), "SO");
    cpu_ov = tcg_global_mem_new(TCG_AREG0,
                                offsetof(CPUPPCState, ov), "OV");
    cpu_ca = tcg_global_mem_new(TCG_AREG0,
                                offsetof(CPUPPCState, ca), "CA");
A
aurel32 已提交
167

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

172 173
    cpu_fpscr = tcg_global_mem_new(TCG_AREG0,
                                   offsetof(CPUPPCState, fpscr), "fpscr");
174

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

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

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

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

209 210 211 212 213 214 215
/* True when active word size < size of target_long.  */
#ifdef TARGET_PPC64
# define NARROW_MODE(C)  (!(C)->sf_mode)
#else
# define NARROW_MODE(C)  0
#endif

A
Anthony Liguori 已提交
216
struct opc_handler_t {
217 218 219 220
    /* invalid bits for instruction 1 (Rc(opcode) == 0) */
    uint32_t inval1;
    /* invalid bits for instruction 2 (Rc(opcode) == 1) */
    uint32_t inval2;
221
    /* instruction type */
222
    uint64_t type;
223 224
    /* extended instruction type */
    uint64_t type2;
B
bellard 已提交
225 226
    /* handler */
    void (*handler)(DisasContext *ctx);
227
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
228
    const char *oname;
229 230
#endif
#if defined(DO_PPC_STATISTICS)
231 232
    uint64_t count;
#endif
233
};
B
bellard 已提交
234

B
Blue Swirl 已提交
235
static inline void gen_reset_fpstatus(void)
236
{
237
    gen_helper_reset_fpstatus(cpu_env);
238 239
}

B
Blue Swirl 已提交
240
static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
241
{
242
    TCGv_i32 t0 = tcg_temp_new_i32();
A
aurel32 已提交
243

244 245
    if (set_fprf != 0) {
        /* This case might be optimized later */
246
        tcg_gen_movi_i32(t0, 1);
247
        gen_helper_compute_fprf(t0, cpu_env, arg, t0);
P
pbrook 已提交
248
        if (unlikely(set_rc)) {
249
            tcg_gen_mov_i32(cpu_crf[1], t0);
P
pbrook 已提交
250
        }
251
        gen_helper_float_check_status(cpu_env);
252 253
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
254
        tcg_gen_movi_i32(t0, 0);
255
        gen_helper_compute_fprf(t0, cpu_env, arg, t0);
256
        tcg_gen_mov_i32(cpu_crf[1], t0);
257
    }
A
aurel32 已提交
258

259
    tcg_temp_free_i32(t0);
260 261
}

B
Blue Swirl 已提交
262
static inline void gen_set_access_type(DisasContext *ctx, int access_type)
A
aurel32 已提交
263
{
A
aurel32 已提交
264 265 266 267
    if (ctx->access_type != access_type) {
        tcg_gen_movi_i32(cpu_access_type, access_type);
        ctx->access_type = access_type;
    }
A
aurel32 已提交
268 269
}

B
Blue Swirl 已提交
270
static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
271
{
272 273 274 275
    if (NARROW_MODE(ctx)) {
        nip = (uint32_t)nip;
    }
    tcg_gen_movi_tl(cpu_nip, nip);
276 277
}

B
Blue Swirl 已提交
278
static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
A
aurel32 已提交
279 280 281 282 283 284 285
{
    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);
286
    gen_helper_raise_exception_err(cpu_env, t0, t1);
A
aurel32 已提交
287 288 289 290
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
    ctx->exception = (excp);
}
291

B
Blue Swirl 已提交
292
static inline void gen_exception(DisasContext *ctx, uint32_t excp)
A
aurel32 已提交
293 294 295 296 297 298
{
    TCGv_i32 t0;
    if (ctx->exception == POWERPC_EXCP_NONE) {
        gen_update_nip(ctx, ctx->nip);
    }
    t0 = tcg_const_i32(excp);
299
    gen_helper_raise_exception(cpu_env, t0);
A
aurel32 已提交
300 301 302
    tcg_temp_free_i32(t0);
    ctx->exception = (excp);
}
303

B
Blue Swirl 已提交
304
static inline void gen_debug_exception(DisasContext *ctx)
A
aurel32 已提交
305 306
{
    TCGv_i32 t0;
B
blueswir1 已提交
307

308 309
    if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
        (ctx->exception != POWERPC_EXCP_SYNC)) {
B
blueswir1 已提交
310
        gen_update_nip(ctx, ctx->nip);
311
    }
A
aurel32 已提交
312
    t0 = tcg_const_i32(EXCP_DEBUG);
313
    gen_helper_raise_exception(cpu_env, t0);
A
aurel32 已提交
314 315
    tcg_temp_free_i32(t0);
}
316

B
Blue Swirl 已提交
317
static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
A
aurel32 已提交
318 319 320
{
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
}
321

322
/* Stop translation */
B
Blue Swirl 已提交
323
static inline void gen_stop_exception(DisasContext *ctx)
324
{
325
    gen_update_nip(ctx, ctx->nip);
326
    ctx->exception = POWERPC_EXCP_STOP;
327 328
}

329
/* No need to update nip here, as execution flow will change */
B
Blue Swirl 已提交
330
static inline void gen_sync_exception(DisasContext *ctx)
331
{
332
    ctx->exception = POWERPC_EXCP_SYNC;
333 334
}

B
bellard 已提交
335
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
336 337 338 339
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 已提交
340

341
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
342 343 344 345
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)
346

A
Anthony Liguori 已提交
347
typedef struct opcode_t {
B
bellard 已提交
348
    unsigned char opc1, opc2, opc3;
T
ths 已提交
349
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
350 351 352 353
    unsigned char pad[5];
#else
    unsigned char pad[1];
#endif
A
Anthony Liguori 已提交
354
    opc_handler_t handler;
355
    const char *oname;
A
Anthony Liguori 已提交
356
} opcode_t;
B
bellard 已提交
357

358
/*****************************************************************************/
B
bellard 已提交
359 360
/***                           Instruction decoding                        ***/
#define EXTRACT_HELPER(name, shift, nb)                                       \
B
Blue Swirl 已提交
361
static inline uint32_t name(uint32_t opcode)                                  \
B
bellard 已提交
362 363 364 365 366
{                                                                             \
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
}

#define EXTRACT_SHELPER(name, shift, nb)                                      \
B
Blue Swirl 已提交
367
static inline int32_t name(uint32_t opcode)                                   \
B
bellard 已提交
368
{                                                                             \
369
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
B
bellard 已提交
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
}

/* 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 */
397
EXTRACT_HELPER(_SPR, 11, 10);
B
Blue Swirl 已提交
398
static inline uint32_t SPR(uint32_t opcode)
399 400 401 402 403
{
    uint32_t sprn = _SPR(opcode);

    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
}
B
bellard 已提交
404 405 406 407 408 409
/***                              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);
410 411
/* 5 bits signed immediate value */
EXTRACT_HELPER(SIMM5, 16, 5);
412 413
/* 5 bits signed immediate value */
EXTRACT_HELPER(UIMM5, 16, 5);
B
bellard 已提交
414 415 416 417
/* Bit count */
EXTRACT_HELPER(NB, 11, 5);
/* Shift count */
EXTRACT_HELPER(SH, 11, 5);
A
aurel32 已提交
418 419
/* Vector shift count */
EXTRACT_HELPER(VSH, 6, 4);
B
bellard 已提交
420 421 422 423
/* Mask start */
EXTRACT_HELPER(MB, 6, 5);
/* Mask end */
EXTRACT_HELPER(ME, 1, 5);
B
bellard 已提交
424 425
/* Trap operand */
EXTRACT_HELPER(TO, 21, 5);
B
bellard 已提交
426 427 428

EXTRACT_HELPER(CRM, 12, 8);
EXTRACT_HELPER(SR, 16, 4);
429 430 431

/* mtfsf/mtfsfi */
EXTRACT_HELPER(FPBF, 19, 3);
A
aurel32 已提交
432
EXTRACT_HELPER(FPIMM, 12, 4);
433 434 435
EXTRACT_HELPER(FPL, 21, 1);
EXTRACT_HELPER(FPFLM, 17, 8);
EXTRACT_HELPER(FPW, 16, 1);
B
bellard 已提交
436

B
bellard 已提交
437 438 439 440
/***                            Jump target decoding                       ***/
/* Displacement */
EXTRACT_SHELPER(d, 0, 16);
/* Immediate address */
B
Blue Swirl 已提交
441
static inline target_ulong LI(uint32_t opcode)
B
bellard 已提交
442 443 444 445
{
    return (opcode >> 0) & 0x03FFFFFC;
}

B
Blue Swirl 已提交
446
static inline uint32_t BD(uint32_t opcode)
B
bellard 已提交
447 448 449 450 451 452 453 454 455 456 457 458
{
    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 已提交
459
static inline target_ulong MASK(uint32_t start, uint32_t end)
B
bellard 已提交
460
{
461
    target_ulong ret;
B
bellard 已提交
462

463 464
#if defined(TARGET_PPC64)
    if (likely(start == 0)) {
465
        ret = UINT64_MAX << (63 - end);
466
    } else if (likely(end == 63)) {
467
        ret = UINT64_MAX >> start;
468 469 470
    }
#else
    if (likely(start == 0)) {
471
        ret = UINT32_MAX << (31  - end);
472
    } else if (likely(end == 31)) {
473
        ret = UINT32_MAX >> start;
474 475 476 477 478 479 480 481
    }
#endif
    else {
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
            (((target_ulong)(-1ULL) >> (end)) >> 1);
        if (unlikely(start > end))
            return ~ret;
    }
B
bellard 已提交
482 483 484 485

    return ret;
}

486 487
/*****************************************************************************/
/* PowerPC instructions table                                                */
B
bellard 已提交
488

489
#if defined(DO_PPC_STATISTICS)
490
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
491
{                                                                             \
B
bellard 已提交
492 493 494
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
495
    .pad  = { 0, },                                                           \
B
bellard 已提交
496
    .handler = {                                                              \
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
        .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,                                                     \
514
        .type = _typ,                                                         \
515
        .type2 = _typ2,                                                       \
B
bellard 已提交
516
        .handler = &gen_##name,                                               \
517
        .oname = stringify(name),                                             \
B
bellard 已提交
518
    },                                                                        \
519
    .oname = stringify(name),                                                 \
B
bellard 已提交
520
}
521
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
522
{                                                                             \
523 524 525 526 527
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
528
        .inval1  = invl,                                                      \
529
        .type = _typ,                                                         \
530
        .type2 = _typ2,                                                       \
531 532 533 534 535
        .handler = &gen_##name,                                               \
        .oname = onam,                                                        \
    },                                                                        \
    .oname = onam,                                                            \
}
536
#else
537
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
538
{                                                                             \
539 540 541 542 543
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
        .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,                                                     \
560
        .type = _typ,                                                         \
561
        .type2 = _typ2,                                                       \
562
        .handler = &gen_##name,                                               \
563 564 565
    },                                                                        \
    .oname = stringify(name),                                                 \
}
566
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
567 568 569 570 571 572
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
573
        .inval1  = invl,                                                      \
574
        .type = _typ,                                                         \
575
        .type2 = _typ2,                                                       \
576 577 578 579 580
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = onam,                                                            \
}
#endif
581

582
/* SPR load/store helpers */
B
Blue Swirl 已提交
583
static inline void gen_load_spr(TCGv t, int reg)
584
{
585
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
586
}
587

B
Blue Swirl 已提交
588
static inline void gen_store_spr(int reg, TCGv t)
589
{
590
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
591
}
592

593
/* Invalid instruction */
B
Blue Swirl 已提交
594
static void gen_invalid(DisasContext *ctx)
595
{
A
aurel32 已提交
596
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
597 598
}

A
Anthony Liguori 已提交
599
static opc_handler_t invalid_handler = {
600 601
    .inval1  = 0xFFFFFFFF,
    .inval2  = 0xFFFFFFFF,
602
    .type    = PPC_NONE,
603
    .type2   = PPC_NONE,
B
bellard 已提交
604 605 606
    .handler = gen_invalid,
};

607 608
/***                           Integer comparison                          ***/

B
Blue Swirl 已提交
609
static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
610
{
611 612
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
613

614
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
615

616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
    tcg_gen_setcond_tl((s ? TCG_COND_LT: TCG_COND_LTU), t0, arg0, arg1);
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_gen_shli_i32(t1, t1, CRF_LT);
    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);

    tcg_gen_setcond_tl((s ? TCG_COND_GT: TCG_COND_GTU), t0, arg0, arg1);
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_gen_shli_i32(t1, t1, CRF_GT);
    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);

    tcg_gen_setcond_tl(TCG_COND_EQ, t0, arg0, arg1);
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_gen_shli_i32(t1, t1, CRF_EQ);
    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);

    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
633 634
}

B
Blue Swirl 已提交
635
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
636
{
637
    TCGv t0 = tcg_const_tl(arg1);
638 639
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
640 641
}

B
Blue Swirl 已提交
642
static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
643
{
644
    TCGv t0, t1;
645 646
    t0 = tcg_temp_new();
    t1 = tcg_temp_new();
647
    if (s) {
648 649
        tcg_gen_ext32s_tl(t0, arg0);
        tcg_gen_ext32s_tl(t1, arg1);
650
    } else {
651 652
        tcg_gen_ext32u_tl(t0, arg0);
        tcg_gen_ext32u_tl(t1, arg1);
653
    }
654 655 656
    gen_op_cmp(t0, t1, s, crf);
    tcg_temp_free(t1);
    tcg_temp_free(t0);
657 658
}

B
Blue Swirl 已提交
659
static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
660
{
661
    TCGv t0 = tcg_const_tl(arg1);
662 663
    gen_op_cmp32(arg0, t0, s, crf);
    tcg_temp_free(t0);
664 665
}

B
Blue Swirl 已提交
666
static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
667
{
668
    if (NARROW_MODE(ctx)) {
669
        gen_op_cmpi32(reg, 0, 1, 0);
670
    } else {
671
        gen_op_cmpi(reg, 0, 1, 0);
672
    }
673 674 675
}

/* cmp */
B
Blue Swirl 已提交
676
static void gen_cmp(DisasContext *ctx)
677
{
678
    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
679 680
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   1, crfD(ctx->opcode));
681 682 683
    } else {
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     1, crfD(ctx->opcode));
684
    }
685 686 687
}

/* cmpi */
B
Blue Swirl 已提交
688
static void gen_cmpi(DisasContext *ctx)
689
{
690
    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
691 692
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                    1, crfD(ctx->opcode));
693 694 695
    } else {
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                      1, crfD(ctx->opcode));
696
    }
697 698 699
}

/* cmpl */
B
Blue Swirl 已提交
700
static void gen_cmpl(DisasContext *ctx)
701
{
702
    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
703 704
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   0, crfD(ctx->opcode));
705 706 707
    } else {
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     0, crfD(ctx->opcode));
708
    }
709 710 711
}

/* cmpli */
B
Blue Swirl 已提交
712
static void gen_cmpli(DisasContext *ctx)
713
{
714
    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
715 716
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                    0, crfD(ctx->opcode));
717 718 719
    } else {
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                      0, crfD(ctx->opcode));
720
    }
721 722 723
}

/* isel (PowerPC 2.03 specification) */
B
Blue Swirl 已提交
724
static void gen_isel(DisasContext *ctx)
725 726 727 728
{
    int l1, l2;
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;
P
pbrook 已提交
729
    TCGv_i32 t0;
730 731 732 733 734

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

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

749 750 751 752 753 754 755
/* cmpb: PowerPC 2.05 specification */
static void gen_cmpb(DisasContext *ctx)
{
    gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
}

B
bellard 已提交
756 757
/***                           Integer arithmetic                          ***/

B
Blue Swirl 已提交
758 759
static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
                                           TCGv arg1, TCGv arg2, int sub)
760
{
761
    TCGv t0 = tcg_temp_new();
B
bellard 已提交
762

763
    tcg_gen_xor_tl(cpu_ov, arg0, arg2);
764
    tcg_gen_xor_tl(t0, arg1, arg2);
765 766 767 768 769 770
    if (sub) {
        tcg_gen_and_tl(cpu_ov, cpu_ov, t0);
    } else {
        tcg_gen_andc_tl(cpu_ov, cpu_ov, t0);
    }
    tcg_temp_free(t0);
771
    if (NARROW_MODE(ctx)) {
772 773 774 775
        tcg_gen_ext32s_tl(cpu_ov, cpu_ov);
    }
    tcg_gen_shri_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1);
    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
B
bellard 已提交
776 777
}

778
/* Common add function */
B
Blue Swirl 已提交
779
static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
780 781
                                    TCGv arg2, bool add_ca, bool compute_ca,
                                    bool compute_ov, bool compute_rc0)
782
{
783
    TCGv t0 = ret;
784

785
    if (compute_ca || compute_ov) {
786
        t0 = tcg_temp_new();
787
    }
B
bellard 已提交
788

789
    if (compute_ca) {
790
        if (NARROW_MODE(ctx)) {
791 792 793
            /* Caution: a non-obvious corner case of the spec is that we
               must produce the *entire* 64-bit addition, but produce the
               carry into bit 32.  */
794
            TCGv t1 = tcg_temp_new();
795 796
            tcg_gen_xor_tl(t1, arg1, arg2);        /* add without carry */
            tcg_gen_add_tl(t0, arg1, arg2);
797 798 799
            if (add_ca) {
                tcg_gen_add_tl(t0, t0, cpu_ca);
            }
800 801 802 803
            tcg_gen_xor_tl(cpu_ca, t0, t1);        /* bits changed w/ carry */
            tcg_temp_free(t1);
            tcg_gen_shri_tl(cpu_ca, cpu_ca, 32);   /* extract bit 32 */
            tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
804
        } else {
805 806 807 808 809 810 811 812
            TCGv zero = tcg_const_tl(0);
            if (add_ca) {
                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero);
                tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero);
            } else {
                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero);
            }
            tcg_temp_free(zero);
813 814 815 816 817 818
        }
    } else {
        tcg_gen_add_tl(t0, arg1, arg2);
        if (add_ca) {
            tcg_gen_add_tl(t0, t0, cpu_ca);
        }
819
    }
B
bellard 已提交
820

821 822 823
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
    }
824
    if (unlikely(compute_rc0)) {
825
        gen_set_Rc0(ctx, t0);
826
    }
827

P
pbrook 已提交
828
    if (!TCGV_EQUAL(t0, ret)) {
829 830 831
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
832
}
833 834
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
835
static void glue(gen_, name)(DisasContext *ctx)                               \
836 837 838
{                                                                             \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
839
                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
840 841 842 843
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
                                add_ca, compute_ca, compute_ov)               \
844
static void glue(gen_, name)(DisasContext *ctx)                               \
845
{                                                                             \
846
    TCGv t0 = tcg_const_tl(const_val);                                        \
847 848
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
849
                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
    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 已提交
869
static void gen_addi(DisasContext *ctx)
870
{
871 872 873 874 875 876
    target_long simm = SIMM(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        /* li case */
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
    } else {
877 878
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
                        cpu_gpr[rA(ctx->opcode)], simm);
879
    }
880
}
881
/* addic  addic.*/
882
static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
883
{
884 885 886 887
    TCGv c = tcg_const_tl(SIMM(ctx->opcode));
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                     c, 0, 1, 0, compute_rc0);
    tcg_temp_free(c);
888
}
B
Blue Swirl 已提交
889 890

static void gen_addic(DisasContext *ctx)
891
{
892
    gen_op_addic(ctx, 0);
893
}
B
Blue Swirl 已提交
894 895

static void gen_addic_(DisasContext *ctx)
896
{
897
    gen_op_addic(ctx, 1);
898
}
B
Blue Swirl 已提交
899

900
/* addis */
B
Blue Swirl 已提交
901
static void gen_addis(DisasContext *ctx)
902
{
903 904 905 906 907 908
    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 {
909 910
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
                        cpu_gpr[rA(ctx->opcode)], simm << 16);
911
    }
912
}
913

B
Blue Swirl 已提交
914 915
static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign, int compute_ov)
916
{
917 918
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
919 920
    TCGv_i32 t0 = tcg_temp_local_new_i32();
    TCGv_i32 t1 = tcg_temp_local_new_i32();
921

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

    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
    if (sign) {
978
        int l3 = gen_new_label();
979 980 981 982 983 984 985 986
        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) {
987
        tcg_gen_movi_tl(cpu_ov, 0);
988 989 990 991 992 993 994 995 996
    }
    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) {
997 998
        tcg_gen_movi_tl(cpu_ov, 1);
        tcg_gen_movi_tl(cpu_so, 1);
999 1000 1001 1002
    }
    gen_set_label(l2);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
1003
}
1004
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
B
Blue Swirl 已提交
1005
static void glue(gen_, name)(DisasContext *ctx)                                       \
1006
{                                                                             \
1007 1008 1009
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      sign, compute_ov);                                      \
1010 1011 1012 1013 1014 1015 1016
}
/* 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);
1017
#endif
1018 1019

/* mulhw  mulhw. */
B
Blue Swirl 已提交
1020
static void gen_mulhw(DisasContext *ctx)
1021
{
1022 1023
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1024

1025 1026 1027 1028 1029 1030
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_muls2_i32(t0, t1, t0, t1);
    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
1031 1032
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1033
}
B
Blue Swirl 已提交
1034

1035
/* mulhwu  mulhwu.  */
B
Blue Swirl 已提交
1036
static void gen_mulhwu(DisasContext *ctx)
1037
{
1038 1039
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1040

1041 1042 1043 1044 1045 1046
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mulu2_i32(t0, t1, t0, t1);
    tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
1047 1048
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1049
}
B
Blue Swirl 已提交
1050

1051
/* mullw  mullw. */
B
Blue Swirl 已提交
1052
static void gen_mullw(DisasContext *ctx)
1053
{
1054 1055
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
1056
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1057 1058
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1059
}
B
Blue Swirl 已提交
1060

1061
/* mullwo  mullwo. */
B
Blue Swirl 已提交
1062
static void gen_mullwo(DisasContext *ctx)
1063
{
1064 1065
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1066

1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_muls2_i32(t0, t1, t0, t1);
    tcg_gen_ext_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);

    tcg_gen_sari_i32(t0, t0, 31);
    tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1);
    tcg_gen_extu_i32_tl(cpu_ov, t0);
    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);

    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
1079 1080
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1081
}
B
Blue Swirl 已提交
1082

1083
/* mulli */
B
Blue Swirl 已提交
1084
static void gen_mulli(DisasContext *ctx)
1085
{
1086 1087
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                    SIMM(ctx->opcode));
1088
}
1089

1090
#if defined(TARGET_PPC64)
1091
/* mulhd  mulhd. */
1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
static void gen_mulhd(DisasContext *ctx)
{
    TCGv lo = tcg_temp_new();
    tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(lo);
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
    }
}

1103
/* mulhdu  mulhdu. */
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
static void gen_mulhdu(DisasContext *ctx)
{
    TCGv lo = tcg_temp_new();
    tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(lo);
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
    }
}
B
Blue Swirl 已提交
1114

1115
/* mulld  mulld. */
B
Blue Swirl 已提交
1116
static void gen_mulld(DisasContext *ctx)
1117
{
1118 1119 1120 1121
    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)]);
1122
}
1123

1124
/* mulldo  mulldo. */
1125 1126 1127 1128 1129 1130 1131 1132
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)]);
    }
}
1133
#endif
1134 1135

/* Common subf function */
B
Blue Swirl 已提交
1136
static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
1137 1138
                                     TCGv arg2, bool add_ca, bool compute_ca,
                                     bool compute_ov, bool compute_rc0)
B
bellard 已提交
1139
{
1140
    TCGv t0 = ret;
B
bellard 已提交
1141

1142
    if (compute_ca || compute_ov) {
1143
        t0 = tcg_temp_new();
1144
    }
1145

1146 1147 1148
    if (compute_ca) {
        /* dest = ~arg1 + arg2 [+ ca].  */
        if (NARROW_MODE(ctx)) {
1149 1150 1151
            /* Caution: a non-obvious corner case of the spec is that we
               must produce the *entire* 64-bit addition, but produce the
               carry into bit 32.  */
1152
            TCGv inv1 = tcg_temp_new();
1153
            TCGv t1 = tcg_temp_new();
1154 1155
            tcg_gen_not_tl(inv1, arg1);
            if (add_ca) {
1156
                tcg_gen_add_tl(t0, arg2, cpu_ca);
1157
            } else {
1158
                tcg_gen_addi_tl(t0, arg2, 1);
1159
            }
1160
            tcg_gen_xor_tl(t1, arg2, inv1);         /* add without carry */
1161
            tcg_gen_add_tl(t0, t0, inv1);
1162 1163 1164 1165
            tcg_gen_xor_tl(cpu_ca, t0, t1);         /* bits changes w/ carry */
            tcg_temp_free(t1);
            tcg_gen_shri_tl(cpu_ca, cpu_ca, 32);    /* extract bit 32 */
            tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
1166
        } else if (add_ca) {
R
Richard Henderson 已提交
1167 1168
            TCGv zero, inv1 = tcg_temp_new();
            tcg_gen_not_tl(inv1, arg1);
1169 1170
            zero = tcg_const_tl(0);
            tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero);
R
Richard Henderson 已提交
1171
            tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero);
1172
            tcg_temp_free(zero);
R
Richard Henderson 已提交
1173
            tcg_temp_free(inv1);
1174
        } else {
1175
            tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
1176 1177
            tcg_gen_sub_tl(t0, arg2, arg1);
        }
1178 1179 1180 1181 1182 1183
    } else if (add_ca) {
        /* Since we're ignoring carry-out, we can simplify the
           standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1.  */
        tcg_gen_sub_tl(t0, arg2, arg1);
        tcg_gen_add_tl(t0, t0, cpu_ca);
        tcg_gen_subi_tl(t0, t0, 1);
B
bellard 已提交
1184
    } else {
1185
        tcg_gen_sub_tl(t0, arg2, arg1);
1186
    }
1187

1188 1189 1190
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
    }
1191
    if (unlikely(compute_rc0)) {
1192
        gen_set_Rc0(ctx, t0);
1193
    }
1194

P
pbrook 已提交
1195
    if (!TCGV_EQUAL(t0, ret)) {
1196 1197
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
B
bellard 已提交
1198 1199
    }
}
1200 1201
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
1202
static void glue(gen_, name)(DisasContext *ctx)                               \
1203 1204 1205
{                                                                             \
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1206
                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1207 1208 1209 1210
}
/* Sub functions with one operand and one immediate */
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
                                add_ca, compute_ca, compute_ov)               \
1211
static void glue(gen_, name)(DisasContext *ctx)                               \
1212
{                                                                             \
1213
    TCGv t0 = tcg_const_tl(const_val);                                        \
1214 1215
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], t0,                           \
1216
                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233
    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 已提交
1234

1235
/* subfic */
B
Blue Swirl 已提交
1236
static void gen_subfic(DisasContext *ctx)
B
bellard 已提交
1237
{
1238 1239 1240 1241
    TCGv c = tcg_const_tl(SIMM(ctx->opcode));
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                      c, 0, 1, 0, 0);
    tcg_temp_free(c);
B
bellard 已提交
1242 1243
}

1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262
/* neg neg. nego nego. */
static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
{
    TCGv zero = tcg_const_tl(0);
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                      zero, 0, 0, compute_ov, Rc(ctx->opcode));
    tcg_temp_free(zero);
}

static void gen_neg(DisasContext *ctx)
{
    gen_op_arith_neg(ctx, 0);
}

static void gen_nego(DisasContext *ctx)
{
    gen_op_arith_neg(ctx, 1);
}

B
bellard 已提交
1263
/***                            Integer logical                            ***/
1264
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1265
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1266
{                                                                             \
1267 1268
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
       cpu_gpr[rB(ctx->opcode)]);                                             \
1269
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1270
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1271 1272
}

1273
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1274
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1275
{                                                                             \
1276
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1277
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1278
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1279 1280 1281
}

/* and & and. */
1282
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
B
bellard 已提交
1283
/* andc & andc. */
1284
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
B
Blue Swirl 已提交
1285

1286
/* andi. */
B
Blue Swirl 已提交
1287
static void gen_andi_(DisasContext *ctx)
B
bellard 已提交
1288
{
1289 1290
    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 已提交
1291
}
B
Blue Swirl 已提交
1292

1293
/* andis. */
B
Blue Swirl 已提交
1294
static void gen_andis_(DisasContext *ctx)
B
bellard 已提交
1295
{
1296 1297
    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 已提交
1298
}
B
Blue Swirl 已提交
1299

1300
/* cntlzw */
B
Blue Swirl 已提交
1301
static void gen_cntlzw(DisasContext *ctx)
1302
{
P
pbrook 已提交
1303
    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1304
    if (unlikely(Rc(ctx->opcode) != 0))
P
pbrook 已提交
1305
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1306
}
B
bellard 已提交
1307
/* eqv & eqv. */
1308
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
B
bellard 已提交
1309
/* extsb & extsb. */
1310
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
B
bellard 已提交
1311
/* extsh & extsh. */
1312
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
B
bellard 已提交
1313
/* nand & nand. */
1314
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
B
bellard 已提交
1315
/* nor & nor. */
1316
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
B
Blue Swirl 已提交
1317

1318
/* or & or. */
B
Blue Swirl 已提交
1319
static void gen_or(DisasContext *ctx)
1320
{
1321 1322 1323 1324 1325 1326 1327
    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) {
1328 1329 1330 1331
        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]);
1332
        if (unlikely(Rc(ctx->opcode) != 0))
1333
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1334
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1335
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1336 1337
#if defined(TARGET_PPC64)
    } else {
1338 1339
        int prio = 0;

1340 1341 1342
        switch (rs) {
        case 1:
            /* Set process priority to low */
1343
            prio = 2;
1344 1345 1346
            break;
        case 6:
            /* Set process priority to medium-low */
1347
            prio = 3;
1348 1349 1350
            break;
        case 2:
            /* Set process priority to normal */
1351
            prio = 4;
1352
            break;
1353 1354
#if !defined(CONFIG_USER_ONLY)
        case 31:
A
aurel32 已提交
1355
            if (ctx->mem_idx > 0) {
1356
                /* Set process priority to very low */
1357
                prio = 1;
1358 1359 1360
            }
            break;
        case 5:
A
aurel32 已提交
1361
            if (ctx->mem_idx > 0) {
1362
                /* Set process priority to medium-hight */
1363
                prio = 5;
1364 1365 1366
            }
            break;
        case 3:
A
aurel32 已提交
1367
            if (ctx->mem_idx > 0) {
1368
                /* Set process priority to high */
1369
                prio = 6;
1370 1371 1372
            }
            break;
        case 7:
A
aurel32 已提交
1373
            if (ctx->mem_idx > 1) {
1374
                /* Set process priority to very high */
1375
                prio = 7;
1376 1377 1378
            }
            break;
#endif
1379 1380 1381 1382
        default:
            /* nop */
            break;
        }
1383
        if (prio) {
P
pbrook 已提交
1384
            TCGv t0 = tcg_temp_new();
1385
            gen_load_spr(t0, SPR_PPR);
1386 1387
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1388
            gen_store_spr(SPR_PPR, t0);
1389
            tcg_temp_free(t0);
1390
        }
1391
#endif
1392 1393
    }
}
B
bellard 已提交
1394
/* orc & orc. */
1395
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
B
Blue Swirl 已提交
1396

1397
/* xor & xor. */
B
Blue Swirl 已提交
1398
static void gen_xor(DisasContext *ctx)
1399 1400
{
    /* Optimisation for "set to zero" case */
1401
    if (rS(ctx->opcode) != rB(ctx->opcode))
A
aurel32 已提交
1402
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1403 1404
    else
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1405
    if (unlikely(Rc(ctx->opcode) != 0))
1406
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1407
}
B
Blue Swirl 已提交
1408

1409
/* ori */
B
Blue Swirl 已提交
1410
static void gen_ori(DisasContext *ctx)
B
bellard 已提交
1411
{
1412
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1413

1414 1415
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
1416
        /* XXX: should handle special NOPs for POWER series */
1417
        return;
1418
    }
1419
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1420
}
B
Blue Swirl 已提交
1421

1422
/* oris */
B
Blue Swirl 已提交
1423
static void gen_oris(DisasContext *ctx)
B
bellard 已提交
1424
{
1425
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1426

1427 1428 1429
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1430
    }
1431
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1432
}
B
Blue Swirl 已提交
1433

1434
/* xori */
B
Blue Swirl 已提交
1435
static void gen_xori(DisasContext *ctx)
B
bellard 已提交
1436
{
1437
    target_ulong uimm = UIMM(ctx->opcode);
1438 1439 1440 1441 1442

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

1446
/* xoris */
B
Blue Swirl 已提交
1447
static void gen_xoris(DisasContext *ctx)
B
bellard 已提交
1448
{
1449
    target_ulong uimm = UIMM(ctx->opcode);
1450 1451 1452 1453 1454

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

1458
/* popcntb : PowerPC 2.03 specification */
B
Blue Swirl 已提交
1459
static void gen_popcntb(DisasContext *ctx)
1460
{
1461 1462 1463 1464 1465 1466 1467 1468
    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)]);
}

1469
#if defined(TARGET_PPC64)
1470 1471 1472 1473
/* popcntd: PowerPC 2.06 specification */
static void gen_popcntd(DisasContext *ctx)
{
    gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1474
}
1475
#endif
1476

1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508
/* prtyw: PowerPC 2.05 specification */
static void gen_prtyw(DisasContext *ctx)
{
    TCGv ra = cpu_gpr[rA(ctx->opcode)];
    TCGv rs = cpu_gpr[rS(ctx->opcode)];
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, rs, 16);
    tcg_gen_xor_tl(ra, rs, t0);
    tcg_gen_shri_tl(t0, ra, 8);
    tcg_gen_xor_tl(ra, ra, t0);
    tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL);
    tcg_temp_free(t0);
}

#if defined(TARGET_PPC64)
/* prtyd: PowerPC 2.05 specification */
static void gen_prtyd(DisasContext *ctx)
{
    TCGv ra = cpu_gpr[rA(ctx->opcode)];
    TCGv rs = cpu_gpr[rS(ctx->opcode)];
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, rs, 32);
    tcg_gen_xor_tl(ra, rs, t0);
    tcg_gen_shri_tl(t0, ra, 16);
    tcg_gen_xor_tl(ra, ra, t0);
    tcg_gen_shri_tl(t0, ra, 8);
    tcg_gen_xor_tl(ra, ra, t0);
    tcg_gen_andi_tl(ra, ra, 1);
    tcg_temp_free(t0);
}
#endif

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

1513
/* cntlzd */
B
Blue Swirl 已提交
1514
static void gen_cntlzd(DisasContext *ctx)
1515
{
P
pbrook 已提交
1516
    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1517 1518 1519
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1520 1521
#endif

B
bellard 已提交
1522
/***                             Integer rotate                            ***/
B
Blue Swirl 已提交
1523

1524
/* rlwimi & rlwimi. */
B
Blue Swirl 已提交
1525
static void gen_rlwimi(DisasContext *ctx)
B
bellard 已提交
1526
{
1527
    uint32_t mb, me, sh;
B
bellard 已提交
1528 1529 1530

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1531
    sh = SH(ctx->opcode);
1532 1533 1534 1535
    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 已提交
1536 1537
        TCGv t1;
        TCGv t0 = tcg_temp_new();
1538
#if defined(TARGET_PPC64)
P
pbrook 已提交
1539 1540 1541 1542 1543
        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);
1544 1545 1546
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1547
#if defined(TARGET_PPC64)
1548 1549
        mb += 32;
        me += 32;
1550
#endif
1551
        mask = MASK(mb, me);
P
pbrook 已提交
1552
        t1 = tcg_temp_new();
1553 1554 1555 1556 1557 1558
        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);
    }
1559
    if (unlikely(Rc(ctx->opcode) != 0))
1560
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1561
}
B
Blue Swirl 已提交
1562

1563
/* rlwinm & rlwinm. */
B
Blue Swirl 已提交
1564
static void gen_rlwinm(DisasContext *ctx)
B
bellard 已提交
1565 1566
{
    uint32_t mb, me, sh;
1567

B
bellard 已提交
1568 1569 1570
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1571 1572 1573 1574 1575

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

1610
/* rlwnm & rlwnm. */
B
Blue Swirl 已提交
1611
static void gen_rlwnm(DisasContext *ctx)
B
bellard 已提交
1612 1613
{
    uint32_t mb, me;
1614 1615
    TCGv t0;
#if defined(TARGET_PPC64)
P
pbrook 已提交
1616
    TCGv_i32 t1, t2;
1617
#endif
B
bellard 已提交
1618 1619 1620

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1621
    t0 = tcg_temp_new();
1622
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1623
#if defined(TARGET_PPC64)
P
pbrook 已提交
1624 1625
    t1 = tcg_temp_new_i32();
    t2 = tcg_temp_new_i32();
1626 1627 1628 1629
    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 已提交
1630 1631
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
1632 1633 1634
#else
    tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
#endif
1635 1636 1637 1638 1639
    if (unlikely(mb != 0 || me != 31)) {
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
1640
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1641
    } else {
1642
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
B
bellard 已提交
1643
    }
1644
    tcg_temp_free(t0);
1645
    if (unlikely(Rc(ctx->opcode) != 0))
1646
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1647 1648
}

1649 1650
#if defined(TARGET_PPC64)
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1651
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1652 1653 1654
{                                                                             \
    gen_##name(ctx, 0);                                                       \
}                                                                             \
B
Blue Swirl 已提交
1655 1656
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1657 1658 1659 1660
{                                                                             \
    gen_##name(ctx, 1);                                                       \
}
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1661
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1662 1663 1664
{                                                                             \
    gen_##name(ctx, 0, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1665 1666
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1667 1668 1669
{                                                                             \
    gen_##name(ctx, 0, 1);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1670 1671
                                                                              \
static void glue(gen_, name##2)(DisasContext *ctx)                            \
1672 1673 1674
{                                                                             \
    gen_##name(ctx, 1, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1675 1676
                                                                              \
static void glue(gen_, name##3)(DisasContext *ctx)                            \
1677 1678 1679
{                                                                             \
    gen_##name(ctx, 1, 1);                                                    \
}
J
j_mayer 已提交
1680

B
Blue Swirl 已提交
1681 1682
static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
                              uint32_t sh)
J
j_mayer 已提交
1683
{
1684 1685 1686 1687 1688
    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 已提交
1689
        TCGv t0 = tcg_temp_new();
1690
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1691
        if (likely(mb == 0 && me == 63)) {
1692
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1693 1694
        } else {
            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
J
j_mayer 已提交
1695
        }
1696
        tcg_temp_free(t0);
J
j_mayer 已提交
1697 1698
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1699
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
J
j_mayer 已提交
1700
}
1701
/* rldicl - rldicl. */
B
Blue Swirl 已提交
1702
static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1703
{
J
j_mayer 已提交
1704
    uint32_t sh, mb;
1705

J
j_mayer 已提交
1706 1707
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1708
    gen_rldinm(ctx, mb, 63, sh);
1709
}
J
j_mayer 已提交
1710
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1711
/* rldicr - rldicr. */
B
Blue Swirl 已提交
1712
static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1713
{
J
j_mayer 已提交
1714
    uint32_t sh, me;
1715

J
j_mayer 已提交
1716 1717
    sh = SH(ctx->opcode) | (shn << 5);
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1718
    gen_rldinm(ctx, 0, me, sh);
1719
}
J
j_mayer 已提交
1720
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1721
/* rldic - rldic. */
B
Blue Swirl 已提交
1722
static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1723
{
J
j_mayer 已提交
1724
    uint32_t sh, mb;
1725

J
j_mayer 已提交
1726 1727
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1728 1729 1730 1731
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

B
Blue Swirl 已提交
1732
static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
J
j_mayer 已提交
1733
{
1734
    TCGv t0;
1735

P
pbrook 已提交
1736
    t0 = tcg_temp_new();
1737
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1738
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
J
j_mayer 已提交
1739
    if (unlikely(mb != 0 || me != 63)) {
1740 1741 1742 1743 1744
        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 已提交
1745
    if (unlikely(Rc(ctx->opcode) != 0))
1746
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1747
}
J
j_mayer 已提交
1748

1749
/* rldcl - rldcl. */
B
Blue Swirl 已提交
1750
static inline void gen_rldcl(DisasContext *ctx, int mbn)
1751
{
J
j_mayer 已提交
1752
    uint32_t mb;
1753

J
j_mayer 已提交
1754
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1755
    gen_rldnm(ctx, mb, 63);
1756
}
1757
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1758
/* rldcr - rldcr. */
B
Blue Swirl 已提交
1759
static inline void gen_rldcr(DisasContext *ctx, int men)
1760
{
J
j_mayer 已提交
1761
    uint32_t me;
1762

J
j_mayer 已提交
1763
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1764
    gen_rldnm(ctx, 0, me);
1765
}
1766
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1767
/* rldimi - rldimi. */
B
Blue Swirl 已提交
1768
static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1769
{
1770
    uint32_t sh, mb, me;
1771

J
j_mayer 已提交
1772 1773
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
1774
    me = 63 - sh;
1775 1776 1777 1778 1779 1780
    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 已提交
1781
        t0 = tcg_temp_new();
1782
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
P
pbrook 已提交
1783
        t1 = tcg_temp_new();
1784 1785 1786 1787 1788 1789
        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 已提交
1790 1791
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1792
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1793
}
1794
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1795 1796
#endif

B
bellard 已提交
1797
/***                             Integer shift                             ***/
B
Blue Swirl 已提交
1798

1799
/* slw & slw. */
B
Blue Swirl 已提交
1800
static void gen_slw(DisasContext *ctx)
1801
{
1802
    TCGv t0, t1;
1803

1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817
    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);
1818
    tcg_temp_free(t0);
1819
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1820 1821 1822
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1823

1824
/* sraw & sraw. */
B
Blue Swirl 已提交
1825
static void gen_sraw(DisasContext *ctx)
1826
{
1827
    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
P
pbrook 已提交
1828
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1829 1830 1831
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1832

1833
/* srawi & srawi. */
B
Blue Swirl 已提交
1834
static void gen_srawi(DisasContext *ctx)
B
bellard 已提交
1835
{
1836
    int sh = SH(ctx->opcode);
1837 1838 1839 1840
    TCGv dst = cpu_gpr[rA(ctx->opcode)];
    TCGv src = cpu_gpr[rS(ctx->opcode)];
    if (sh == 0) {
        tcg_gen_mov_tl(dst, src);
1841
        tcg_gen_movi_tl(cpu_ca, 0);
1842
    } else {
1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854
        TCGv t0;
        tcg_gen_ext32s_tl(dst, src);
        tcg_gen_andi_tl(cpu_ca, dst, (1ULL << sh) - 1);
        t0 = tcg_temp_new();
        tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1);
        tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
        tcg_temp_free(t0);
        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
        tcg_gen_sari_tl(dst, dst, sh);
    }
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, dst);
1855
    }
B
bellard 已提交
1856
}
B
Blue Swirl 已提交
1857

1858
/* srw & srw. */
B
Blue Swirl 已提交
1859
static void gen_srw(DisasContext *ctx)
1860
{
1861
    TCGv t0, t1;
1862

1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
    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 已提交
1874
    t1 = tcg_temp_new();
1875 1876
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1877 1878
    tcg_temp_free(t1);
    tcg_temp_free(t0);
1879 1880 1881
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1882

1883 1884
#if defined(TARGET_PPC64)
/* sld & sld. */
B
Blue Swirl 已提交
1885
static void gen_sld(DisasContext *ctx)
1886
{
1887
    TCGv t0, t1;
1888

1889 1890 1891 1892 1893 1894 1895 1896 1897
    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);
1898
    tcg_temp_free(t0);
1899 1900 1901
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
1902

1903
/* srad & srad. */
B
Blue Swirl 已提交
1904
static void gen_srad(DisasContext *ctx)
1905
{
1906
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
P
pbrook 已提交
1907
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1908 1909 1910
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1911
/* sradi & sradi. */
B
Blue Swirl 已提交
1912
static inline void gen_sradi(DisasContext *ctx, int n)
1913
{
1914
    int sh = SH(ctx->opcode) + (n << 5);
1915 1916 1917 1918
    TCGv dst = cpu_gpr[rA(ctx->opcode)];
    TCGv src = cpu_gpr[rS(ctx->opcode)];
    if (sh == 0) {
        tcg_gen_mov_tl(dst, src);
1919
        tcg_gen_movi_tl(cpu_ca, 0);
1920
    } else {
1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931
        TCGv t0;
        tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
        t0 = tcg_temp_new();
        tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1);
        tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
        tcg_temp_free(t0);
        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
        tcg_gen_sari_tl(dst, src, sh);
    }
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, dst);
1932 1933
    }
}
B
Blue Swirl 已提交
1934 1935

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

static void gen_sradi1(DisasContext *ctx)
1941 1942 1943
{
    gen_sradi(ctx, 1);
}
B
Blue Swirl 已提交
1944

1945
/* srd & srd. */
B
Blue Swirl 已提交
1946
static void gen_srd(DisasContext *ctx)
1947
{
1948
    TCGv t0, t1;
1949

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

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

1987 1988 1989
#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);
1990

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

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

2039
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
B
Blue Swirl 已提交
2040
static void gen_f##name(DisasContext *ctx)                                    \
2041
{                                                                             \
2042
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2043
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2044 2045
        return;                                                               \
    }                                                                         \
2046 2047
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2048
    gen_reset_fpstatus();                                                     \
2049 2050
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
                       cpu_fpr[rB(ctx->opcode)]);                             \
A
aurel32 已提交
2051 2052
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2053 2054
}

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

2071
/* fadd - fadds */
2072
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2073
/* fdiv - fdivs */
2074
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2075
/* fmul - fmuls */
2076
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2077

2078
/* fre */
2079
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2080

2081
/* fres */
2082
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2083

2084
/* frsqrte */
2085 2086 2087
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
B
Blue Swirl 已提交
2088
static void gen_frsqrtes(DisasContext *ctx)
2089
{
A
aurel32 已提交
2090
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2091
        gen_exception(ctx, POWERPC_EXCP_FPU);
A
aurel32 已提交
2092 2093
        return;
    }
2094 2095
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2096
    gen_reset_fpstatus();
2097 2098 2099 2100
    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 已提交
2101
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2102
}
B
bellard 已提交
2103

2104
/* fsel */
2105
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2106
/* fsub - fsubs */
2107
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2108
/* Optional: */
B
Blue Swirl 已提交
2109

2110
/* fsqrt */
B
Blue Swirl 已提交
2111
static void gen_fsqrt(DisasContext *ctx)
2112
{
2113
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2114
        gen_exception(ctx, POWERPC_EXCP_FPU);
2115 2116
        return;
    }
2117 2118
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2119
    gen_reset_fpstatus();
2120 2121
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
                     cpu_fpr[rB(ctx->opcode)]);
A
aurel32 已提交
2122
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2123
}
B
bellard 已提交
2124

B
Blue Swirl 已提交
2125
static void gen_fsqrts(DisasContext *ctx)
B
bellard 已提交
2126
{
2127
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2128
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2129 2130
        return;
    }
2131 2132
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2133
    gen_reset_fpstatus();
2134 2135 2136 2137
    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 已提交
2138
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
B
bellard 已提交
2139 2140 2141
}

/***                     Floating-Point multiply-and-add                   ***/
2142
/* fmadd - fmadds */
2143
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2144
/* fmsub - fmsubs */
2145
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2146
/* fnmadd - fnmadds */
2147
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2148
/* fnmsub - fnmsubs */
2149
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2150 2151 2152

/***                     Floating-Point round & convert                    ***/
/* fctiw */
2153
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2154
/* fctiwz */
2155
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2156
/* frsp */
2157
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
2158 2159
#if defined(TARGET_PPC64)
/* fcfid */
2160
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
2161
/* fctid */
2162
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2163
/* fctidz */
2164
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2165
#endif
B
bellard 已提交
2166

2167
/* frin */
2168
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2169
/* friz */
2170
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2171
/* frip */
2172
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2173
/* frim */
2174
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2175

B
bellard 已提交
2176
/***                         Floating-Point compare                        ***/
B
Blue Swirl 已提交
2177

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

/* fcmpu */
B
Blue Swirl 已提交
2197
static void gen_fcmpu(DisasContext *ctx)
B
bellard 已提交
2198
{
A
aurel32 已提交
2199
    TCGv_i32 crf;
2200
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2201
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2202 2203
        return;
    }
2204 2205
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2206
    gen_reset_fpstatus();
A
aurel32 已提交
2207
    crf = tcg_const_i32(crfD(ctx->opcode));
2208 2209
    gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
                     cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2210
    tcg_temp_free_i32(crf);
2211
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2212 2213
}

2214 2215
/***                         Floating-point move                           ***/
/* fabs */
2216
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2217 2218 2219 2220 2221 2222 2223 2224 2225 2226
static void gen_fabs(DisasContext *ctx)
{
    if (unlikely(!ctx->fpu_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_FPU);
        return;
    }
    tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
                     ~(1ULL << 63));
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
}
2227 2228

/* fmr  - fmr. */
2229
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
B
Blue Swirl 已提交
2230
static void gen_fmr(DisasContext *ctx)
2231
{
2232
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2233
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2234 2235
        return;
    }
A
aurel32 已提交
2236 2237
    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);
2238 2239 2240
}

/* fnabs */
2241
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252
static void gen_fnabs(DisasContext *ctx)
{
    if (unlikely(!ctx->fpu_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_FPU);
        return;
    }
    tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
                    1ULL << 63);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
}

2253
/* fneg */
2254
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
static void gen_fneg(DisasContext *ctx)
{
    if (unlikely(!ctx->fpu_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_FPU);
        return;
    }
    tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
                     1ULL << 63);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
}
2265

2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
/* fcpsgn: PowerPC 2.05 specification */
/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
static void gen_fcpsgn(DisasContext *ctx)
{
    if (unlikely(!ctx->fpu_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_FPU);
        return;
    }
    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
                        cpu_fpr[rB(ctx->opcode)], 0, 63);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
}

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

2281
/* mcrfs */
B
Blue Swirl 已提交
2282
static void gen_mcrfs(DisasContext *ctx)
B
bellard 已提交
2283
{
2284
    TCGv tmp = tcg_temp_new();
2285 2286
    int bfa;

2287
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2288
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2289 2290
        return;
    }
2291
    bfa = 4 * (7 - crfS(ctx->opcode));
2292 2293 2294
    tcg_gen_shri_tl(tmp, cpu_fpscr, bfa);
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
    tcg_temp_free(tmp);
2295
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2296
    tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
B
bellard 已提交
2297 2298 2299
}

/* mffs */
B
Blue Swirl 已提交
2300
static void gen_mffs(DisasContext *ctx)
B
bellard 已提交
2301
{
2302
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2303
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2304 2305
        return;
    }
2306
    gen_reset_fpstatus();
2307
    tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
A
aurel32 已提交
2308
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2309 2310 2311
}

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

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

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

2341
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2342
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2343 2344
        return;
    }
A
aurel32 已提交
2345
    crb = 31 - crbD(ctx->opcode);
2346 2347
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
A
aurel32 已提交
2348
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2349 2350 2351 2352
        TCGv_i32 t0;
        /* NIP cannot be restored if the memory exception comes from an helper */
        gen_update_nip(ctx, ctx->nip - 4);
        t0 = tcg_const_i32(crb);
2353
        gen_helper_fpscr_setbit(cpu_env, t0);
2354
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2355
    }
2356
    if (unlikely(Rc(ctx->opcode) != 0)) {
2357 2358
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2359 2360
    }
    /* We can raise a differed exception */
2361
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2362 2363 2364
}

/* mtfsf */
B
Blue Swirl 已提交
2365
static void gen_mtfsf(DisasContext *ctx)
B
bellard 已提交
2366
{
2367
    TCGv_i32 t0;
2368
    int flm, l, w;
A
aurel32 已提交
2369

2370
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2371
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2372 2373
        return;
    }
2374 2375 2376 2377 2378 2379 2380
    flm = FPFLM(ctx->opcode);
    l = FPL(ctx->opcode);
    w = FPW(ctx->opcode);
    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        return;
    }
2381 2382
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2383
    gen_reset_fpstatus();
2384 2385 2386 2387 2388
    if (l) {
        t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
    } else {
        t0 = tcg_const_i32(flm << (w * 8));
    }
2389
    gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
2390
    tcg_temp_free_i32(t0);
2391
    if (unlikely(Rc(ctx->opcode) != 0)) {
2392 2393
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2394 2395
    }
    /* We can raise a differed exception */
2396
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2397 2398 2399
}

/* mtfsfi */
B
Blue Swirl 已提交
2400
static void gen_mtfsfi(DisasContext *ctx)
B
bellard 已提交
2401
{
2402
    int bf, sh, w;
2403 2404
    TCGv_i64 t0;
    TCGv_i32 t1;
2405

2406
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2407
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2408 2409
        return;
    }
2410 2411 2412 2413 2414 2415 2416
    w = FPW(ctx->opcode);
    bf = FPBF(ctx->opcode);
    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        return;
    }
    sh = (8 * w) + 7 - bf;
2417 2418
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2419
    gen_reset_fpstatus();
2420
    t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
A
aurel32 已提交
2421
    t1 = tcg_const_i32(1 << sh);
2422
    gen_helper_store_fpscr(cpu_env, t0, t1);
2423 2424
    tcg_temp_free_i64(t0);
    tcg_temp_free_i32(t1);
2425
    if (unlikely(Rc(ctx->opcode) != 0)) {
2426 2427
        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
2428 2429
    }
    /* We can raise a differed exception */
2430
    gen_helper_float_check_status(cpu_env);
B
bellard 已提交
2431 2432
}

2433 2434
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
B
Blue Swirl 已提交
2435 2436
static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
                                      target_long maskl)
2437 2438 2439
{
    target_long simm = SIMM(ctx->opcode);

2440
    simm &= ~maskl;
A
aurel32 已提交
2441
    if (rA(ctx->opcode) == 0) {
2442 2443 2444
        if (NARROW_MODE(ctx)) {
            simm = (uint32_t)simm;
        }
2445
        tcg_gen_movi_tl(EA, simm);
A
aurel32 已提交
2446
    } else if (likely(simm != 0)) {
2447
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2448
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2449 2450 2451
            tcg_gen_ext32u_tl(EA, EA);
        }
    } else {
2452
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2453
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2454 2455 2456
        } else {
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
        }
A
aurel32 已提交
2457
    }
2458 2459
}

B
Blue Swirl 已提交
2460
static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2461
{
A
aurel32 已提交
2462
    if (rA(ctx->opcode) == 0) {
2463
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2464
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2465 2466 2467
        } else {
            tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
        }
A
aurel32 已提交
2468
    } else {
2469
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2470
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2471 2472 2473
            tcg_gen_ext32u_tl(EA, EA);
        }
    }
2474 2475
}

B
Blue Swirl 已提交
2476
static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2477
{
A
aurel32 已提交
2478
    if (rA(ctx->opcode) == 0) {
2479
        tcg_gen_movi_tl(EA, 0);
2480 2481
    } else if (NARROW_MODE(ctx)) {
        tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2482
    } else {
2483
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2484 2485 2486
    }
}

B
Blue Swirl 已提交
2487 2488
static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                target_long val)
A
aurel32 已提交
2489 2490
{
    tcg_gen_addi_tl(ret, arg1, val);
2491
    if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2492 2493
        tcg_gen_ext32u_tl(ret, ret);
    }
2494 2495
}

B
Blue Swirl 已提交
2496
static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
{
    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);
2507
    gen_helper_raise_exception_err(cpu_env, t1, t2);
2508 2509 2510 2511 2512 2513
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    gen_set_label(l1);
    tcg_temp_free(t0);
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2673 2674 2675 2676 2677
#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 已提交
2678 2679

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

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

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

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

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

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

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

2805 2806
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2807
{                                                                             \
A
aurel32 已提交
2808 2809 2810 2811 2812
    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 已提交
2813
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2814
}
2815 2816
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
B
bellard 已提交
2817

2818 2819 2820 2821 2822
#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 已提交
2823 2824

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

static void gen_std(DisasContext *ctx)
2835
{
2836
    int rs;
A
aurel32 已提交
2837
    TCGv EA;
2838 2839 2840 2841

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

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

2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916
#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 已提交
2917
/* sthbrx */
2918
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2919
{
A
aurel32 已提交
2920 2921 2922
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2923
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2924 2925 2926 2927 2928
        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 已提交
2929
}
2930
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
A
aurel32 已提交
2931

B
bellard 已提交
2932
/* stwbrx */
2933
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2934
{
A
aurel32 已提交
2935
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2936 2937 2938
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2939 2940 2941 2942 2943
        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 已提交
2944
}
2945
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2946

2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962
#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 已提交
2963
/***                    Integer load and store multiple                    ***/
B
Blue Swirl 已提交
2964

2965
/* lmw */
B
Blue Swirl 已提交
2966
static void gen_lmw(DisasContext *ctx)
B
bellard 已提交
2967
{
A
aurel32 已提交
2968 2969 2970
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2971
    /* NIP cannot be restored if the memory exception comes from an helper */
2972
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2973 2974 2975
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rD(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2976
    gen_helper_lmw(cpu_env, t0, t1);
2977 2978
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2979 2980 2981
}

/* stmw */
B
Blue Swirl 已提交
2982
static void gen_stmw(DisasContext *ctx)
B
bellard 已提交
2983
{
A
aurel32 已提交
2984 2985 2986
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2987
    /* NIP cannot be restored if the memory exception comes from an helper */
2988
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2989 2990 2991
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rS(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2992
    gen_helper_stmw(cpu_env, t0, t1);
2993 2994
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2995 2996 2997
}

/***                    Integer load and store strings                     ***/
2998

B
bellard 已提交
2999
/* lswi */
3000
/* PowerPC32 specification says we must generate an exception if
3001 3002 3003 3004
 * 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 已提交
3005
static void gen_lswi(DisasContext *ctx)
B
bellard 已提交
3006
{
3007 3008
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3009 3010
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
3011
    int ra = rA(ctx->opcode);
B
bellard 已提交
3012 3013 3014 3015 3016
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
3017 3018 3019
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
A
aurel32 已提交
3020
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3021
        return;
B
bellard 已提交
3022
    }
A
aurel32 已提交
3023
    gen_set_access_type(ctx, ACCESS_INT);
3024
    /* NIP cannot be restored if the memory exception comes from an helper */
3025
    gen_update_nip(ctx, ctx->nip - 4);
3026
    t0 = tcg_temp_new();
A
aurel32 已提交
3027
    gen_addr_register(ctx, t0);
3028 3029
    t1 = tcg_const_i32(nb);
    t2 = tcg_const_i32(start);
3030
    gen_helper_lsw(cpu_env, t0, t1, t2);
3031 3032 3033
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3034 3035 3036
}

/* lswx */
B
Blue Swirl 已提交
3037
static void gen_lswx(DisasContext *ctx)
B
bellard 已提交
3038
{
A
aurel32 已提交
3039 3040 3041
    TCGv t0;
    TCGv_i32 t1, t2, t3;
    gen_set_access_type(ctx, ACCESS_INT);
3042
    /* NIP cannot be restored if the memory exception comes from an helper */
3043
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3044 3045 3046 3047 3048
    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));
3049
    gen_helper_lswx(cpu_env, t0, t1, t2, t3);
3050 3051 3052 3053
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
B
bellard 已提交
3054 3055 3056
}

/* stswi */
B
Blue Swirl 已提交
3057
static void gen_stswi(DisasContext *ctx)
B
bellard 已提交
3058
{
A
aurel32 已提交
3059 3060
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3061
    int nb = NB(ctx->opcode);
A
aurel32 已提交
3062
    gen_set_access_type(ctx, ACCESS_INT);
3063
    /* NIP cannot be restored if the memory exception comes from an helper */
3064
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3065 3066
    t0 = tcg_temp_new();
    gen_addr_register(ctx, t0);
B
bellard 已提交
3067 3068
    if (nb == 0)
        nb = 32;
3069
    t1 = tcg_const_i32(nb);
A
aurel32 已提交
3070
    t2 = tcg_const_i32(rS(ctx->opcode));
3071
    gen_helper_stsw(cpu_env, t0, t1, t2);
3072 3073 3074
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3075 3076 3077
}

/* stswx */
B
Blue Swirl 已提交
3078
static void gen_stswx(DisasContext *ctx)
B
bellard 已提交
3079
{
A
aurel32 已提交
3080 3081 3082
    TCGv t0;
    TCGv_i32 t1, t2;
    gen_set_access_type(ctx, ACCESS_INT);
3083
    /* NIP cannot be restored if the memory exception comes from an helper */
3084
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3085 3086 3087
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_temp_new_i32();
3088 3089
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
    tcg_gen_andi_i32(t1, t1, 0x7F);
A
aurel32 已提交
3090
    t2 = tcg_const_i32(rS(ctx->opcode));
3091
    gen_helper_stsw(cpu_env, t0, t1, t2);
3092 3093 3094
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3095 3096 3097 3098
}

/***                        Memory synchronisation                         ***/
/* eieio */
B
Blue Swirl 已提交
3099
static void gen_eieio(DisasContext *ctx)
B
bellard 已提交
3100 3101 3102 3103
{
}

/* isync */
B
Blue Swirl 已提交
3104
static void gen_isync(DisasContext *ctx)
B
bellard 已提交
3105
{
A
aurel32 已提交
3106
    gen_stop_exception(ctx);
B
bellard 已提交
3107 3108
}

3109
/* lwarx */
B
Blue Swirl 已提交
3110
static void gen_lwarx(DisasContext *ctx)
B
bellard 已提交
3111
{
A
aurel32 已提交
3112
    TCGv t0;
3113
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3114 3115 3116
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3117
    gen_check_align(ctx, t0, 0x03);
3118
    gen_qemu_ld32u(ctx, gpr, t0);
3119
    tcg_gen_mov_tl(cpu_reserve, t0);
3120
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3121
    tcg_temp_free(t0);
B
bellard 已提交
3122 3123
}

3124 3125 3126 3127 3128 3129 3130
#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;

3131
    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
3132
    tcg_gen_movi_tl(t0, (size << 5) | reg);
3133
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
3134 3135 3136 3137 3138 3139 3140 3141
    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 已提交
3142
/* stwcx. */
B
Blue Swirl 已提交
3143
static void gen_stwcx_(DisasContext *ctx)
B
bellard 已提交
3144
{
A
aurel32 已提交
3145 3146 3147 3148
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3149
    gen_check_align(ctx, t0, 0x03);
3150 3151 3152 3153 3154 3155
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
#else
    {
        int l1;

3156
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3157 3158 3159 3160 3161 3162 3163 3164
        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
3165
    tcg_temp_free(t0);
B
bellard 已提交
3166 3167
}

J
j_mayer 已提交
3168 3169
#if defined(TARGET_PPC64)
/* ldarx */
B
Blue Swirl 已提交
3170
static void gen_ldarx(DisasContext *ctx)
J
j_mayer 已提交
3171
{
A
aurel32 已提交
3172
    TCGv t0;
3173
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
A
aurel32 已提交
3174 3175 3176
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3177
    gen_check_align(ctx, t0, 0x07);
3178
    gen_qemu_ld64(ctx, gpr, t0);
3179
    tcg_gen_mov_tl(cpu_reserve, t0);
3180
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
3181
    tcg_temp_free(t0);
J
j_mayer 已提交
3182 3183 3184
}

/* stdcx. */
B
Blue Swirl 已提交
3185
static void gen_stdcx_(DisasContext *ctx)
J
j_mayer 已提交
3186
{
A
aurel32 已提交
3187 3188 3189 3190
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3191
    gen_check_align(ctx, t0, 0x07);
3192 3193 3194 3195 3196
#if defined(CONFIG_USER_ONLY)
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
#else
    {
        int l1;
3197
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3198 3199 3200 3201 3202 3203 3204 3205
        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
3206
    tcg_temp_free(t0);
J
j_mayer 已提交
3207 3208 3209
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3210
/* sync */
B
Blue Swirl 已提交
3211
static void gen_sync(DisasContext *ctx)
B
bellard 已提交
3212 3213 3214
{
}

3215
/* wait */
B
Blue Swirl 已提交
3216
static void gen_wait(DisasContext *ctx)
3217
{
3218
    TCGv_i32 t0 = tcg_temp_new_i32();
3219 3220
    tcg_gen_st_i32(t0, cpu_env,
                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
3221
    tcg_temp_free_i32(t0);
3222
    /* Stop translation, as the CPU is supposed to sleep from now */
A
aurel32 已提交
3223
    gen_exception_err(ctx, EXCP_HLT, 1);
3224 3225
}

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

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

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

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

3297 3298 3299 3300 3301 3302
#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 已提交
3303
static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3304 3305 3306
{
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
A
aurel32 已提交
3307
    gen_qemu_ld32u(ctx, t0, arg2);
3308 3309
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_temp_free(t0);
3310
    gen_helper_float32_to_float64(arg1, cpu_env, t1);
3311 3312
    tcg_temp_free_i32(t1);
}
B
bellard 已提交
3313

3314 3315 3316 3317
 /* lfd lfdu lfdux lfdx */
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3318

3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364
/* lfdp */
static void gen_lfdp(DisasContext *ctx)
{
    TCGv EA;
    if (unlikely(!ctx->fpu_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_FPU);
        return;
    }
    gen_set_access_type(ctx, ACCESS_FLOAT);
    EA = tcg_temp_new();
    gen_addr_imm_index(ctx, EA, 0);                                           \
    if (unlikely(ctx->le_mode)) {
        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
    } else {
        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
    }
    tcg_temp_free(EA);
}

/* lfdpx */
static void gen_lfdpx(DisasContext *ctx)
{
    TCGv EA;
    if (unlikely(!ctx->fpu_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_FPU);
        return;
    }
    gen_set_access_type(ctx, ACCESS_FLOAT);
    EA = tcg_temp_new();
    gen_addr_reg_index(ctx, EA);
    if (unlikely(ctx->le_mode)) {
        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
    } else {
        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
    }
    tcg_temp_free(EA);
}

3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377
/* lfiwax */
static void gen_lfiwax(DisasContext *ctx)
{
    TCGv EA;
    TCGv t0;
    if (unlikely(!ctx->fpu_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_FPU);
        return;
    }
    gen_set_access_type(ctx, ACCESS_FLOAT);
    EA = tcg_temp_new();
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, EA);
3378
    gen_qemu_ld32s(ctx, t0, EA);
3379 3380 3381 3382 3383
    tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
    tcg_temp_free(EA);
    tcg_temp_free(t0);
}

B
bellard 已提交
3384
/***                         Floating-point store                          ***/
3385
#define GEN_STF(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
3386
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3387
{                                                                             \
3388
    TCGv EA;                                                                  \
3389
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3390
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3391 3392
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3393
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3394
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3395 3396
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3397
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3398 3399
}

3400
#define GEN_STUF(name, stop, opc, type)                                       \
B
Blue Swirl 已提交
3401
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
3402
{                                                                             \
3403
    TCGv EA;                                                                  \
3404
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3405
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3406 3407
        return;                                                               \
    }                                                                         \
3408
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3409
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3410
        return;                                                               \
3411
    }                                                                         \
A
aurel32 已提交
3412
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3413
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3414 3415
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3416 3417
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3418 3419
}

3420
#define GEN_STUXF(name, stop, opc, type)                                      \
B
Blue Swirl 已提交
3421
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
3422
{                                                                             \
3423
    TCGv EA;                                                                  \
3424
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3425
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3426 3427
        return;                                                               \
    }                                                                         \
3428
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3429
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3430
        return;                                                               \
3431
    }                                                                         \
A
aurel32 已提交
3432
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3433
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3434 3435
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3436 3437
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3438 3439
}

3440
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
3441
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
B
bellard 已提交
3442
{                                                                             \
3443
    TCGv EA;                                                                  \
3444
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3445
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3446 3447
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3448
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3449
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3450 3451
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3452
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3453 3454
}

3455 3456 3457 3458 3459 3460
#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 已提交
3461
static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3462 3463 3464
{
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv t1 = tcg_temp_new();
3465
    gen_helper_float64_to_float32(t0, cpu_env, arg1);
3466 3467
    tcg_gen_extu_i32_tl(t1, t0);
    tcg_temp_free_i32(t0);
A
aurel32 已提交
3468
    gen_qemu_st32(ctx, t1, arg2);
3469 3470
    tcg_temp_free(t1);
}
B
bellard 已提交
3471 3472

/* stfd stfdu stfdux stfdx */
3473
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
B
bellard 已提交
3474
/* stfs stfsu stfsux stfsx */
3475
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3476

3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522
/* stfdp */
static void gen_stfdp(DisasContext *ctx)
{
    TCGv EA;
    if (unlikely(!ctx->fpu_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_FPU);
        return;
    }
    gen_set_access_type(ctx, ACCESS_FLOAT);
    EA = tcg_temp_new();
    gen_addr_imm_index(ctx, EA, 0);                                           \
    if (unlikely(ctx->le_mode)) {
        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
    } else {
        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
    }
    tcg_temp_free(EA);
}

/* stfdpx */
static void gen_stfdpx(DisasContext *ctx)
{
    TCGv EA;
    if (unlikely(!ctx->fpu_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_FPU);
        return;
    }
    gen_set_access_type(ctx, ACCESS_FLOAT);
    EA = tcg_temp_new();
    gen_addr_reg_index(ctx, EA);
    if (unlikely(ctx->le_mode)) {
        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
    } else {
        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
    }
    tcg_temp_free(EA);
}

B
bellard 已提交
3523
/* Optional: */
B
Blue Swirl 已提交
3524
static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3525 3526 3527
{
    TCGv t0 = tcg_temp_new();
    tcg_gen_trunc_i64_tl(t0, arg1),
A
aurel32 已提交
3528
    gen_qemu_st32(ctx, t0, arg2);
3529 3530
    tcg_temp_free(t0);
}
B
bellard 已提交
3531
/* stfiwx */
3532
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3533

D
David Gibson 已提交
3534 3535 3536 3537 3538 3539 3540 3541
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 已提交
3542
/***                                Branch                                 ***/
B
Blue Swirl 已提交
3543
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3544 3545 3546
{
    TranslationBlock *tb;
    tb = ctx->tb;
3547
    if (NARROW_MODE(ctx)) {
3548
        dest = (uint32_t) dest;
3549
    }
B
bellard 已提交
3550
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3551
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3552
        tcg_gen_goto_tb(n);
3553
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3554
        tcg_gen_exit_tb((tcg_target_long)tb + n);
3555
    } else {
3556
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3557 3558
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3559
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
J
Julio Guerra 已提交
3560 3561
                (ctx->exception == POWERPC_EXCP_BRANCH ||
                 ctx->exception == POWERPC_EXCP_TRACE)) {
3562 3563
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
A
aurel32 已提交
3564
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3565 3566 3567
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3568
                gen_debug_exception(ctx);
3569 3570
            }
        }
B
bellard 已提交
3571
        tcg_gen_exit_tb(0);
3572
    }
B
bellard 已提交
3573 3574
}

B
Blue Swirl 已提交
3575
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3576
{
3577 3578 3579 3580
    if (NARROW_MODE(ctx)) {
        nip = (uint32_t)nip;
    }
    tcg_gen_movi_tl(cpu_lr, nip);
3581 3582
}

B
bellard 已提交
3583
/* b ba bl bla */
B
Blue Swirl 已提交
3584
static void gen_b(DisasContext *ctx)
B
bellard 已提交
3585
{
3586
    target_ulong li, target;
B
bellard 已提交
3587

3588
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3589
    /* sign extend LI */
3590 3591 3592
    li = LI(ctx->opcode);
    li = (li ^ 0x02000000) - 0x02000000;
    if (likely(AA(ctx->opcode) == 0)) {
B
bellard 已提交
3593
        target = ctx->nip + li - 4;
3594
    } else {
3595
        target = li;
3596 3597
    }
    if (LK(ctx->opcode)) {
3598
        gen_setlr(ctx, ctx->nip);
3599
    }
D
David Gibson 已提交
3600
    gen_update_cfar(ctx, ctx->nip);
3601
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3602 3603
}

3604 3605 3606 3607
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

B
Blue Swirl 已提交
3608
static inline void gen_bcond(DisasContext *ctx, int type)
3609 3610
{
    uint32_t bo = BO(ctx->opcode);
3611
    int l1;
3612
    TCGv target;
3613

3614
    ctx->exception = POWERPC_EXCP_BRANCH;
3615
    if (type == BCOND_LR || type == BCOND_CTR) {
P
pbrook 已提交
3616
        target = tcg_temp_local_new();
3617 3618 3619 3620
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3621 3622
    } else {
        TCGV_UNUSED(target);
3623
    }
3624 3625
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3626 3627 3628
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3629
        TCGv temp = tcg_temp_new();
3630
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3631
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3632 3633 3634
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3635
        if (NARROW_MODE(ctx)) {
3636
            tcg_gen_ext32u_tl(temp, cpu_ctr);
3637
        } else {
3638
            tcg_gen_mov_tl(temp, cpu_ctr);
3639
        }
3640 3641 3642 3643
        if (bo & 0x2) {
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
        } else {
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3644
        }
P
pbrook 已提交
3645
        tcg_temp_free(temp);
3646 3647 3648 3649 3650
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
3651
        TCGv_i32 temp = tcg_temp_new_i32();
3652

3653
        if (bo & 0x8) {
3654 3655
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3656
        } else {
3657 3658
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3659
        }
P
pbrook 已提交
3660
        tcg_temp_free_i32(temp);
3661
    }
D
David Gibson 已提交
3662
    gen_update_cfar(ctx, ctx->nip);
3663
    if (type == BCOND_IM) {
3664 3665 3666 3667 3668 3669
        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 已提交
3670
        gen_set_label(l1);
3671
        gen_goto_tb(ctx, 1, ctx->nip);
3672
    } else {
3673
        if (NARROW_MODE(ctx)) {
3674
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3675
        } else {
3676
            tcg_gen_andi_tl(cpu_nip, target, ~3);
3677
        }
3678 3679
        tcg_gen_exit_tb(0);
        gen_set_label(l1);
3680
        gen_update_nip(ctx, ctx->nip);
B
bellard 已提交
3681
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3682
    }
3683 3684
}

B
Blue Swirl 已提交
3685
static void gen_bc(DisasContext *ctx)
3686
{
3687 3688 3689
    gen_bcond(ctx, BCOND_IM);
}

B
Blue Swirl 已提交
3690
static void gen_bcctr(DisasContext *ctx)
3691
{
3692 3693 3694
    gen_bcond(ctx, BCOND_CTR);
}

B
Blue Swirl 已提交
3695
static void gen_bclr(DisasContext *ctx)
3696
{
3697 3698
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3699 3700

/***                      Condition register logical                       ***/
3701
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
B
Blue Swirl 已提交
3702
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3703
{                                                                             \
3704 3705
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
P
pbrook 已提交
3706
    TCGv_i32 t0, t1;                                                          \
3707
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
P
pbrook 已提交
3708
    t0 = tcg_temp_new_i32();                                                  \
3709
    if (sh > 0)                                                               \
3710
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3711
    else if (sh < 0)                                                          \
3712
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3713
    else                                                                      \
3714
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
P
pbrook 已提交
3715
    t1 = tcg_temp_new_i32();                                                  \
3716 3717
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3718
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3719
    else if (sh < 0)                                                          \
3720
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3721
    else                                                                      \
3722 3723
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3724
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3725 3726 3727
    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 已提交
3728 3729
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
B
bellard 已提交
3730 3731 3732
}

/* crand */
3733
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3734
/* crandc */
3735
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3736
/* creqv */
3737
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3738
/* crnand */
3739
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3740
/* crnor */
3741
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3742
/* cror */
3743
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3744
/* crorc */
3745
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3746
/* crxor */
3747
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
Blue Swirl 已提交
3748

3749
/* mcrf */
B
Blue Swirl 已提交
3750
static void gen_mcrf(DisasContext *ctx)
B
bellard 已提交
3751
{
A
aurel32 已提交
3752
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3753 3754 3755
}

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

3757
/* rfi (mem_idx only) */
B
Blue Swirl 已提交
3758
static void gen_rfi(DisasContext *ctx)
B
bellard 已提交
3759
{
3760
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3761
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3762 3763
#else
    /* Restore CPU state */
A
aurel32 已提交
3764
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3765
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3766
        return;
3767
    }
D
David Gibson 已提交
3768
    gen_update_cfar(ctx, ctx->nip);
3769
    gen_helper_rfi(cpu_env);
A
aurel32 已提交
3770
    gen_sync_exception(ctx);
3771
#endif
B
bellard 已提交
3772 3773
}

J
j_mayer 已提交
3774
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3775
static void gen_rfid(DisasContext *ctx)
J
j_mayer 已提交
3776 3777
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3778
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3779 3780
#else
    /* Restore CPU state */
A
aurel32 已提交
3781
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3782
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3783 3784
        return;
    }
D
David Gibson 已提交
3785
    gen_update_cfar(ctx, ctx->nip);
3786
    gen_helper_rfid(cpu_env);
A
aurel32 已提交
3787
    gen_sync_exception(ctx);
J
j_mayer 已提交
3788 3789 3790
#endif
}

B
Blue Swirl 已提交
3791
static void gen_hrfid(DisasContext *ctx)
3792 3793
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3794
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3795 3796
#else
    /* Restore CPU state */
A
aurel32 已提交
3797
    if (unlikely(ctx->mem_idx <= 1)) {
A
aurel32 已提交
3798
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3799 3800
        return;
    }
3801
    gen_helper_hrfid(cpu_env);
A
aurel32 已提交
3802
    gen_sync_exception(ctx);
3803 3804 3805 3806
#endif
}
#endif

B
bellard 已提交
3807
/* sc */
3808 3809 3810 3811 3812
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
B
Blue Swirl 已提交
3813
static void gen_sc(DisasContext *ctx)
B
bellard 已提交
3814
{
3815 3816 3817
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
A
aurel32 已提交
3818
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3819 3820 3821
}

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

3823
/* tw */
B
Blue Swirl 已提交
3824
static void gen_tw(DisasContext *ctx)
B
bellard 已提交
3825
{
3826
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3827 3828
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3829 3830
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3831
    tcg_temp_free_i32(t0);
B
bellard 已提交
3832 3833 3834
}

/* twi */
B
Blue Swirl 已提交
3835
static void gen_twi(DisasContext *ctx)
B
bellard 已提交
3836
{
3837 3838
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3839 3840
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3841
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3842 3843
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3844 3845
}

3846 3847
#if defined(TARGET_PPC64)
/* td */
B
Blue Swirl 已提交
3848
static void gen_td(DisasContext *ctx)
3849
{
3850
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3851 3852
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3853 3854
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3855
    tcg_temp_free_i32(t0);
3856 3857 3858
}

/* tdi */
B
Blue Swirl 已提交
3859
static void gen_tdi(DisasContext *ctx)
3860
{
3861 3862
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3863 3864
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3865
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3866 3867
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
3868 3869 3870
}
#endif

B
bellard 已提交
3871
/***                          Processor control                            ***/
B
Blue Swirl 已提交
3872

3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901
static void gen_read_xer(TCGv dst)
{
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    tcg_gen_mov_tl(dst, cpu_xer);
    tcg_gen_shli_tl(t0, cpu_so, XER_SO);
    tcg_gen_shli_tl(t1, cpu_ov, XER_OV);
    tcg_gen_shli_tl(t2, cpu_ca, XER_CA);
    tcg_gen_or_tl(t0, t0, t1);
    tcg_gen_or_tl(dst, dst, t2);
    tcg_gen_or_tl(dst, dst, t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
}

static void gen_write_xer(TCGv src)
{
    tcg_gen_andi_tl(cpu_xer, src,
                    ~((1u << XER_SO) | (1u << XER_OV) | (1u << XER_CA)));
    tcg_gen_shri_tl(cpu_so, src, XER_SO);
    tcg_gen_shri_tl(cpu_ov, src, XER_OV);
    tcg_gen_shri_tl(cpu_ca, src, XER_CA);
    tcg_gen_andi_tl(cpu_so, cpu_so, 1);
    tcg_gen_andi_tl(cpu_ov, cpu_ov, 1);
    tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
}

3902
/* mcrxr */
B
Blue Swirl 已提交
3903
static void gen_mcrxr(DisasContext *ctx)
B
bellard 已提交
3904
{
3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
    TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];

    tcg_gen_trunc_tl_i32(t0, cpu_so);
    tcg_gen_trunc_tl_i32(t1, cpu_ov);
    tcg_gen_trunc_tl_i32(dst, cpu_ca);
    tcg_gen_shri_i32(t0, t0, 2);
    tcg_gen_shri_i32(t1, t1, 1);
    tcg_gen_or_i32(dst, dst, t0);
    tcg_gen_or_i32(dst, dst, t1);
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);

    tcg_gen_movi_tl(cpu_so, 0);
    tcg_gen_movi_tl(cpu_ov, 0);
    tcg_gen_movi_tl(cpu_ca, 0);
B
bellard 已提交
3922 3923
}

A
aurel32 已提交
3924
/* mfcr mfocrf */
B
Blue Swirl 已提交
3925
static void gen_mfcr(DisasContext *ctx)
B
bellard 已提交
3926
{
3927
    uint32_t crm, crn;
3928

3929 3930
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3931
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3932
            crn = ctz32 (crm);
3933
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3934 3935
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3936
        }
3937
    } else {
A
aurel32 已提交
3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955
        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);
3956
    }
B
bellard 已提交
3957 3958 3959
}

/* mfmsr */
B
Blue Swirl 已提交
3960
static void gen_mfmsr(DisasContext *ctx)
B
bellard 已提交
3961
{
3962
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3963
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3964
#else
A
aurel32 已提交
3965
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3966
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3967
        return;
3968
    }
3969
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3970
#endif
B
bellard 已提交
3971 3972
}

3973
static void spr_noaccess(void *opaque, int gprn, int sprn)
3974
{
3975
#if 0
3976 3977
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
3978
#endif
3979 3980 3981
}
#define SPR_NOACCESS (&spr_noaccess)

B
bellard 已提交
3982
/* mfspr */
B
Blue Swirl 已提交
3983
static inline void gen_op_mfspr(DisasContext *ctx)
B
bellard 已提交
3984
{
A
aurel32 已提交
3985
    void (*read_cb)(void *opaque, int gprn, int sprn);
B
bellard 已提交
3986 3987
    uint32_t sprn = SPR(ctx->opcode);

3988
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3989
    if (ctx->mem_idx == 2)
3990
        read_cb = ctx->spr_cb[sprn].hea_read;
A
aurel32 已提交
3991
    else if (ctx->mem_idx)
3992 3993
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3994
#endif
3995
        read_cb = ctx->spr_cb[sprn].uea_read;
3996 3997
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3998
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3999 4000
        } else {
            /* Privilege exception */
4001 4002 4003 4004 4005
            /* 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) {
4006 4007 4008 4009
                qemu_log("Trying to read privileged spr %d (0x%03x) at "
                         TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
                printf("Trying to read privileged spr %d (0x%03x) at "
                       TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4010
            }
A
aurel32 已提交
4011
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
4012
        }
4013 4014
    } else {
        /* Not defined */
4015 4016 4017 4018
        qemu_log("Trying to read invalid spr %d (0x%03x) at "
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
        printf("Trying to read invalid spr %d (0x%03x) at "
               TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
A
aurel32 已提交
4019
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
4020 4021 4022
    }
}

B
Blue Swirl 已提交
4023
static void gen_mfspr(DisasContext *ctx)
B
bellard 已提交
4024
{
4025
    gen_op_mfspr(ctx);
4026
}
4027 4028

/* mftb */
B
Blue Swirl 已提交
4029
static void gen_mftb(DisasContext *ctx)
4030 4031
{
    gen_op_mfspr(ctx);
B
bellard 已提交
4032 4033
}

A
aurel32 已提交
4034
/* mtcrf mtocrf*/
B
Blue Swirl 已提交
4035
static void gen_mtcrf(DisasContext *ctx)
B
bellard 已提交
4036
{
4037
    uint32_t crm, crn;
4038

4039
    crm = CRM(ctx->opcode);
M
malc 已提交
4040 4041 4042
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
4043
            crn = ctz32 (crm);
M
malc 已提交
4044
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
4045 4046
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
4047 4048
            tcg_temp_free_i32(temp);
        }
4049
    } else {
A
aurel32 已提交
4050 4051 4052 4053 4054 4055 4056 4057
        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 已提交
4058
        tcg_temp_free_i32(temp);
4059
    }
B
bellard 已提交
4060 4061 4062
}

/* mtmsr */
J
j_mayer 已提交
4063
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
4064
static void gen_mtmsrd(DisasContext *ctx)
J
j_mayer 已提交
4065 4066
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4067
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
4068
#else
A
aurel32 已提交
4069
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4070
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
4071 4072
        return;
    }
4073 4074
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
4075 4076 4077 4078 4079
        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);
4080
    } else {
4081 4082 4083 4084
        /* 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
         */
4085
        gen_update_nip(ctx, ctx->nip);
4086
        gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
4087 4088
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
4089
        gen_stop_exception(ctx);
4090
    }
J
j_mayer 已提交
4091 4092 4093 4094
#endif
}
#endif

B
Blue Swirl 已提交
4095
static void gen_mtmsr(DisasContext *ctx)
B
bellard 已提交
4096
{
4097
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4098
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4099
#else
A
aurel32 已提交
4100
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4101
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4102
        return;
4103
    }
4104 4105
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
4106 4107 4108 4109 4110
        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);
4111
    } else {
4112 4113
        TCGv msr = tcg_temp_new();

4114 4115 4116 4117
        /* 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
         */
4118
        gen_update_nip(ctx, ctx->nip);
4119
#if defined(TARGET_PPC64)
4120 4121 4122
        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)]);
4123
#endif
4124
        gen_helper_store_msr(cpu_env, msr);
4125
        /* Must stop the translation as machine state (may have) changed */
4126
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
4127
        gen_stop_exception(ctx);
4128
    }
4129
#endif
B
bellard 已提交
4130 4131 4132
}

/* mtspr */
B
Blue Swirl 已提交
4133
static void gen_mtspr(DisasContext *ctx)
B
bellard 已提交
4134
{
A
aurel32 已提交
4135
    void (*write_cb)(void *opaque, int sprn, int gprn);
B
bellard 已提交
4136 4137
    uint32_t sprn = SPR(ctx->opcode);

4138
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4139
    if (ctx->mem_idx == 2)
4140
        write_cb = ctx->spr_cb[sprn].hea_write;
A
aurel32 已提交
4141
    else if (ctx->mem_idx)
4142 4143
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
4144
#endif
4145
        write_cb = ctx->spr_cb[sprn].uea_write;
4146 4147
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
4148
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
4149 4150
        } else {
            /* Privilege exception */
4151 4152 4153 4154
            qemu_log("Trying to write privileged spr %d (0x%03x) at "
                     TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
            printf("Trying to write privileged spr %d (0x%03x) at "
                   TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
A
aurel32 已提交
4155
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4156
        }
4157 4158
    } else {
        /* Not defined */
4159 4160 4161 4162
        qemu_log("Trying to write invalid spr %d (0x%03x) at "
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
        printf("Trying to write invalid spr %d (0x%03x) at "
               TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
A
aurel32 已提交
4163
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
4164 4165 4166 4167
    }
}

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

4169
/* dcbf */
B
Blue Swirl 已提交
4170
static void gen_dcbf(DisasContext *ctx)
B
bellard 已提交
4171
{
J
j_mayer 已提交
4172
    /* XXX: specification says this is treated as a load by the MMU */
A
aurel32 已提交
4173 4174 4175 4176 4177
    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);
4178
    tcg_temp_free(t0);
B
bellard 已提交
4179 4180 4181
}

/* dcbi (Supervisor only) */
B
Blue Swirl 已提交
4182
static void gen_dcbi(DisasContext *ctx)
B
bellard 已提交
4183
{
4184
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4185
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4186
#else
A
aurel32 已提交
4187
    TCGv EA, val;
A
aurel32 已提交
4188
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4189
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4190
        return;
4191
    }
P
pbrook 已提交
4192
    EA = tcg_temp_new();
A
aurel32 已提交
4193 4194
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
4195
    val = tcg_temp_new();
4196
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
4197 4198
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
4199 4200
    tcg_temp_free(val);
    tcg_temp_free(EA);
4201
#endif
B
bellard 已提交
4202 4203 4204
}

/* dcdst */
B
Blue Swirl 已提交
4205
static void gen_dcbst(DisasContext *ctx)
B
bellard 已提交
4206
{
4207
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
4208 4209 4210 4211 4212
    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);
4213
    tcg_temp_free(t0);
B
bellard 已提交
4214 4215 4216
}

/* dcbt */
B
Blue Swirl 已提交
4217
static void gen_dcbt(DisasContext *ctx)
B
bellard 已提交
4218
{
4219
    /* interpreted as no-op */
4220 4221 4222
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4223 4224 4225
}

/* dcbtst */
B
Blue Swirl 已提交
4226
static void gen_dcbtst(DisasContext *ctx)
B
bellard 已提交
4227
{
4228
    /* interpreted as no-op */
4229 4230 4231
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4232 4233 4234
}

/* dcbz */
B
Blue Swirl 已提交
4235
static void gen_dcbz(DisasContext *ctx)
B
bellard 已提交
4236
{
A
Alexander Graf 已提交
4237 4238 4239
    TCGv tcgv_addr;
    TCGv_i32 tcgv_is_dcbzl;
    int is_dcbzl = ctx->opcode & 0x00200000 ? 1 : 0;
4240

A
aurel32 已提交
4241
    gen_set_access_type(ctx, ACCESS_CACHE);
4242 4243
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
Alexander Graf 已提交
4244 4245 4246 4247 4248 4249 4250 4251
    tcgv_addr = tcg_temp_new();
    tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);

    gen_addr_reg_index(ctx, tcgv_addr);
    gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_is_dcbzl);

    tcg_temp_free(tcgv_addr);
    tcg_temp_free_i32(tcgv_is_dcbzl);
B
bellard 已提交
4252 4253
}

4254
/* dst / dstt */
B
Blue Swirl 已提交
4255
static void gen_dst(DisasContext *ctx)
4256 4257 4258 4259 4260 4261 4262 4263 4264
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }
}

/* dstst /dststt */
B
Blue Swirl 已提交
4265
static void gen_dstst(DisasContext *ctx)
4266 4267 4268 4269 4270 4271 4272 4273 4274 4275
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }

}

/* dss / dssall */
B
Blue Swirl 已提交
4276
static void gen_dss(DisasContext *ctx)
4277 4278 4279 4280
{
    /* interpreted as no-op */
}

B
bellard 已提交
4281
/* icbi */
B
Blue Swirl 已提交
4282
static void gen_icbi(DisasContext *ctx)
B
bellard 已提交
4283
{
A
aurel32 已提交
4284 4285
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4286 4287
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4288 4289
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4290
    gen_helper_icbi(cpu_env, t0);
4291
    tcg_temp_free(t0);
B
bellard 已提交
4292 4293 4294 4295
}

/* Optional: */
/* dcba */
B
Blue Swirl 已提交
4296
static void gen_dcba(DisasContext *ctx)
B
bellard 已提交
4297
{
4298 4299 4300 4301
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4302 4303 4304 4305
}

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

4307
/* mfsr */
B
Blue Swirl 已提交
4308
static void gen_mfsr(DisasContext *ctx)
B
bellard 已提交
4309
{
4310
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4311
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4312
#else
4313
    TCGv t0;
A
aurel32 已提交
4314
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4315
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4316
        return;
4317
    }
4318
    t0 = tcg_const_tl(SR(ctx->opcode));
4319
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4320
    tcg_temp_free(t0);
4321
#endif
B
bellard 已提交
4322 4323 4324
}

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

/* mtsr */
B
Blue Swirl 已提交
4344
static void gen_mtsr(DisasContext *ctx)
B
bellard 已提交
4345
{
4346
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4347
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4348
#else
4349
    TCGv t0;
A
aurel32 已提交
4350
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4351
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4352
        return;
4353
    }
4354
    t0 = tcg_const_tl(SR(ctx->opcode));
4355
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4356
    tcg_temp_free(t0);
4357
#endif
B
bellard 已提交
4358 4359 4360
}

/* mtsrin */
B
Blue Swirl 已提交
4361
static void gen_mtsrin(DisasContext *ctx)
B
bellard 已提交
4362
{
4363
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4364
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4365
#else
4366
    TCGv t0;
A
aurel32 已提交
4367
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4368
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4369
        return;
4370
    }
4371 4372 4373
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4374
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
4375
    tcg_temp_free(t0);
4376
#endif
B
bellard 已提交
4377 4378
}

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

4382
/* mfsr */
B
Blue Swirl 已提交
4383
static void gen_mfsr_64b(DisasContext *ctx)
4384 4385
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4386
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4387
#else
4388
    TCGv t0;
A
aurel32 已提交
4389
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4390
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4391 4392
        return;
    }
4393
    t0 = tcg_const_tl(SR(ctx->opcode));
4394
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4395
    tcg_temp_free(t0);
4396 4397 4398 4399
#endif
}

/* mfsrin */
B
Blue Swirl 已提交
4400
static void gen_mfsrin_64b(DisasContext *ctx)
4401 4402
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4403
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4404
#else
4405
    TCGv t0;
A
aurel32 已提交
4406
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4407
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4408 4409
        return;
    }
4410 4411 4412
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4413
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4414
    tcg_temp_free(t0);
4415 4416 4417 4418
#endif
}

/* mtsr */
B
Blue Swirl 已提交
4419
static void gen_mtsr_64b(DisasContext *ctx)
4420 4421
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4422
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4423
#else
4424
    TCGv t0;
A
aurel32 已提交
4425
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4426
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4427 4428
        return;
    }
4429
    t0 = tcg_const_tl(SR(ctx->opcode));
4430
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4431
    tcg_temp_free(t0);
4432 4433 4434 4435
#endif
}

/* mtsrin */
B
Blue Swirl 已提交
4436
static void gen_mtsrin_64b(DisasContext *ctx)
4437 4438
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4439
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4440
#else
4441
    TCGv t0;
A
aurel32 已提交
4442
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4443
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4444 4445
        return;
    }
4446 4447 4448
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
4449
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4450
    tcg_temp_free(t0);
4451 4452
#endif
}
B
blueswir1 已提交
4453 4454

/* slbmte */
B
Blue Swirl 已提交
4455
static void gen_slbmte(DisasContext *ctx)
B
blueswir1 已提交
4456 4457 4458 4459 4460 4461 4462 4463
{
#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;
    }
4464 4465
    gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
B
blueswir1 已提交
4466 4467 4468
#endif
}

4469 4470 4471 4472 4473 4474 4475 4476 4477
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;
    }
4478
    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491
                             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;
    }
4492
    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4493 4494 4495
                             cpu_gpr[rB(ctx->opcode)]);
#endif
}
4496 4497
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4498
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4499
/* Optional & mem_idx only: */
B
Blue Swirl 已提交
4500

4501
/* tlbia */
B
Blue Swirl 已提交
4502
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4503
{
4504
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4505
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4506
#else
A
aurel32 已提交
4507
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4508
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4509
        return;
4510
    }
4511
    gen_helper_tlbia(cpu_env);
4512
#endif
B
bellard 已提交
4513 4514
}

B
blueswir1 已提交
4515
/* tlbiel */
B
Blue Swirl 已提交
4516
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4517 4518 4519 4520 4521 4522 4523 4524
{
#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;
    }
4525
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
B
blueswir1 已提交
4526 4527 4528
#endif
}

B
bellard 已提交
4529
/* tlbie */
B
Blue Swirl 已提交
4530
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4531
{
4532
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4533
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4534
#else
A
aurel32 已提交
4535
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4536
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4537
        return;
4538
    }
4539
    if (NARROW_MODE(ctx)) {
4540 4541
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4542
        gen_helper_tlbie(cpu_env, t0);
4543
        tcg_temp_free(t0);
4544
    } else {
4545
        gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4546
    }
4547
#endif
B
bellard 已提交
4548 4549 4550
}

/* tlbsync */
B
Blue Swirl 已提交
4551
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4552
{
4553
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4554
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4555
#else
A
aurel32 已提交
4556
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4557
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4558
        return;
4559 4560 4561 4562
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4563
    gen_stop_exception(ctx);
4564
#endif
B
bellard 已提交
4565 4566
}

J
j_mayer 已提交
4567 4568
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4569
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4570 4571
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4572
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4573
#else
A
aurel32 已提交
4574
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4575
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4576 4577
        return;
    }
4578
    gen_helper_slbia(cpu_env);
J
j_mayer 已提交
4579 4580 4581 4582
#endif
}

/* slbie */
B
Blue Swirl 已提交
4583
static void gen_slbie(DisasContext *ctx)
J
j_mayer 已提交
4584 4585
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4586
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4587
#else
A
aurel32 已提交
4588
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4589
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4590 4591
        return;
    }
4592
    gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4593 4594 4595 4596
#endif
}
#endif

B
bellard 已提交
4597 4598
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4599

4600
/* eciwx */
B
Blue Swirl 已提交
4601
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4602
{
A
aurel32 已提交
4603
    TCGv t0;
4604
    /* Should check EAR[E] ! */
A
aurel32 已提交
4605 4606 4607
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4608
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4609
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4610
    tcg_temp_free(t0);
4611 4612 4613
}

/* ecowx */
B
Blue Swirl 已提交
4614
static void gen_ecowx(DisasContext *ctx)
4615
{
A
aurel32 已提交
4616
    TCGv t0;
4617
    /* Should check EAR[E] ! */
A
aurel32 已提交
4618 4619 4620
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4621
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4622
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4623
    tcg_temp_free(t0);
4624 4625 4626
}

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

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

/* abso - abso. */
B
Blue Swirl 已提交
4644
static void gen_abso(DisasContext *ctx)
4645
{
4646 4647 4648 4649
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
4650
    tcg_gen_movi_tl(cpu_ov, 0);
4651 4652
    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);
4653 4654
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4655 4656 4657 4658 4659 4660 4661
    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);
4662
    if (unlikely(Rc(ctx->opcode) != 0))
4663
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4664 4665 4666
}

/* clcs */
B
Blue Swirl 已提交
4667
static void gen_clcs(DisasContext *ctx)
4668
{
4669
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
B
Blue Swirl 已提交
4670
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4671
    tcg_temp_free_i32(t0);
4672
    /* Rc=1 sets CR0 to an undefined state */
4673 4674 4675
}

/* div - div. */
B
Blue Swirl 已提交
4676
static void gen_div(DisasContext *ctx)
4677
{
4678 4679
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
4680
    if (unlikely(Rc(ctx->opcode) != 0))
4681
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4682 4683 4684
}

/* divo - divo. */
B
Blue Swirl 已提交
4685
static void gen_divo(DisasContext *ctx)
4686
{
4687 4688
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4689
    if (unlikely(Rc(ctx->opcode) != 0))
4690
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4691 4692 4693
}

/* divs - divs. */
B
Blue Swirl 已提交
4694
static void gen_divs(DisasContext *ctx)
4695
{
4696 4697
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4698
    if (unlikely(Rc(ctx->opcode) != 0))
4699
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4700 4701 4702
}

/* divso - divso. */
B
Blue Swirl 已提交
4703
static void gen_divso(DisasContext *ctx)
4704
{
4705 4706
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4707
    if (unlikely(Rc(ctx->opcode) != 0))
4708
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4709 4710 4711
}

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

/* dozo - dozo. */
B
Blue Swirl 已提交
4727
static void gen_dozo(DisasContext *ctx)
4728
{
4729 4730 4731 4732 4733 4734
    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 */
4735
    tcg_gen_movi_tl(cpu_ov, 0);
4736 4737 4738 4739 4740 4741 4742
    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);
4743 4744
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4745 4746 4747 4748 4749 4750 4751
    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);
4752
    if (unlikely(Rc(ctx->opcode) != 0))
4753
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4754 4755 4756
}

/* dozi */
B
Blue Swirl 已提交
4757
static void gen_dozi(DisasContext *ctx)
4758
{
4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769
    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)]);
4770 4771 4772
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4773
static void gen_lscbx(DisasContext *ctx)
4774
{
4775 4776 4777 4778
    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));
4779

A
aurel32 已提交
4780
    gen_addr_reg_index(ctx, t0);
4781
    /* NIP cannot be restored if the memory exception comes from an helper */
4782
    gen_update_nip(ctx, ctx->nip - 4);
4783
    gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
4784 4785 4786
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
A
aurel32 已提交
4787
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4788
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4789
    if (unlikely(Rc(ctx->opcode) != 0))
4790 4791
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4792 4793 4794
}

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

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

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

/* mulo - mulo. */
B
Blue Swirl 已提交
4855
static void gen_mulo(DisasContext *ctx)
4856
{
4857 4858 4859 4860 4861
    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 */
4862
    tcg_gen_movi_tl(cpu_ov, 0);
4863 4864 4865 4866 4867 4868 4869 4870 4871
    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);
4872 4873
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4874 4875 4876 4877
    gen_set_label(l1);
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free(t2);
4878
    if (unlikely(Rc(ctx->opcode) != 0))
4879
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4880 4881 4882
}

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

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

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

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

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

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

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

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

/* sllq - sllq. */
B
Blue Swirl 已提交
5024
static void gen_sllq(DisasContext *ctx)
5025
{
5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047
    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);
5048
    if (unlikely(Rc(ctx->opcode) != 0))
5049
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5050 5051 5052
}

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

5075
/* sraiq - sraiq. */
B
Blue Swirl 已提交
5076
static void gen_sraiq(DisasContext *ctx)
5077
{
5078 5079 5080 5081 5082 5083 5084 5085
    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);
5086
    tcg_gen_movi_tl(cpu_ca, 0);
5087 5088
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
5089
    tcg_gen_movi_tl(cpu_ca, 1);
5090 5091 5092 5093
    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);
5094
    if (unlikely(Rc(ctx->opcode) != 0))
5095
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5096 5097 5098
}

/* sraq - sraq. */
B
Blue Swirl 已提交
5099
static void gen_sraq(DisasContext *ctx)
5100
{
5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119
    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);
5120
    tcg_gen_movi_tl(cpu_ca, 0);
5121 5122
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
5123
    tcg_gen_movi_tl(cpu_ca, 1);
5124 5125 5126
    gen_set_label(l2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
5127
    if (unlikely(Rc(ctx->opcode) != 0))
5128
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5129 5130 5131
}

/* sre - sre. */
B
Blue Swirl 已提交
5132
static void gen_sre(DisasContext *ctx)
5133
{
5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144
    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);
5145
    if (unlikely(Rc(ctx->opcode) != 0))
5146
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5147 5148 5149
}

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

/* sreq */
B
Blue Swirl 已提交
5165
static void gen_sreq(DisasContext *ctx)
5166
{
5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181
    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);
5182
    if (unlikely(Rc(ctx->opcode) != 0))
5183
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5184 5185 5186
}

/* sriq */
B
Blue Swirl 已提交
5187
static void gen_sriq(DisasContext *ctx)
5188
{
5189 5190 5191 5192 5193 5194 5195 5196 5197 5198
    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);
5199
    if (unlikely(Rc(ctx->opcode) != 0))
5200
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5201 5202 5203
}

/* srliq */
B
Blue Swirl 已提交
5204
static void gen_srliq(DisasContext *ctx)
5205
{
5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216
    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);
5217
    if (unlikely(Rc(ctx->opcode) != 0))
5218
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5219 5220 5221
}

/* srlq */
B
Blue Swirl 已提交
5222
static void gen_srlq(DisasContext *ctx)
5223
{
5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246
    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);
5247
    if (unlikely(Rc(ctx->opcode) != 0))
5248
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5249 5250 5251
}

/* srq */
B
Blue Swirl 已提交
5252
static void gen_srq(DisasContext *ctx)
5253
{
5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269
    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);
5270
    if (unlikely(Rc(ctx->opcode) != 0))
5271
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5272 5273 5274
}

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

5276
/* dsa  */
B
Blue Swirl 已提交
5277
static void gen_dsa(DisasContext *ctx)
5278 5279
{
    /* XXX: TODO */
A
aurel32 已提交
5280
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5281 5282 5283
}

/* esa */
B
Blue Swirl 已提交
5284
static void gen_esa(DisasContext *ctx)
5285 5286
{
    /* XXX: TODO */
A
aurel32 已提交
5287
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5288 5289 5290
}

/* mfrom */
B
Blue Swirl 已提交
5291
static void gen_mfrom(DisasContext *ctx)
5292 5293
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5294
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5295
#else
A
aurel32 已提交
5296
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5297
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5298 5299
        return;
    }
5300
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5301 5302 5303 5304
#endif
}

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

5306
/* tlbld */
B
Blue Swirl 已提交
5307
static void gen_tlbld_6xx(DisasContext *ctx)
5308 5309
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5310
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5311
#else
A
aurel32 已提交
5312
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5313
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5314 5315
        return;
    }
5316
    gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5317 5318 5319 5320
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5321
static void gen_tlbli_6xx(DisasContext *ctx)
5322 5323
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5324
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5325
#else
A
aurel32 已提交
5326
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5327
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5328 5329
        return;
    }
5330
    gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5331 5332 5333
#endif
}

5334
/* 74xx TLB management */
B
Blue Swirl 已提交
5335

5336
/* tlbld */
B
Blue Swirl 已提交
5337
static void gen_tlbld_74xx(DisasContext *ctx)
5338 5339
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5340
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5341
#else
A
aurel32 已提交
5342
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5343
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5344 5345
        return;
    }
5346
    gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5347 5348 5349 5350
#endif
}

/* tlbli */
B
Blue Swirl 已提交
5351
static void gen_tlbli_74xx(DisasContext *ctx)
5352 5353
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5354
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5355
#else
A
aurel32 已提交
5356
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5357
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5358 5359
        return;
    }
5360
    gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5361 5362 5363
#endif
}

5364
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5365

5366
/* clf */
B
Blue Swirl 已提交
5367
static void gen_clf(DisasContext *ctx)
5368 5369 5370 5371 5372
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5373
static void gen_cli(DisasContext *ctx)
5374
{
B
blueswir1 已提交
5375
    /* Cache line invalidate: privileged and treated as no-op */
5376
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5377
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5378
#else
A
aurel32 已提交
5379
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5380
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5381 5382 5383 5384 5385 5386
        return;
    }
#endif
}

/* dclst */
B
Blue Swirl 已提交
5387
static void gen_dclst(DisasContext *ctx)
5388 5389 5390 5391
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5392
static void gen_mfsri(DisasContext *ctx)
5393 5394
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5395
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5396
#else
5397 5398 5399
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5400
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5401
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5402 5403
        return;
    }
5404
    t0 = tcg_temp_new();
A
aurel32 已提交
5405
    gen_addr_reg_index(ctx, t0);
5406 5407
    tcg_gen_shri_tl(t0, t0, 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
5408
    gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
5409
    tcg_temp_free(t0);
5410
    if (ra != 0 && ra != rd)
5411
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5412 5413 5414
#endif
}

B
Blue Swirl 已提交
5415
static void gen_rac(DisasContext *ctx)
5416 5417
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5418
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5419
#else
5420
    TCGv t0;
A
aurel32 已提交
5421
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5422
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5423 5424
        return;
    }
5425
    t0 = tcg_temp_new();
A
aurel32 已提交
5426
    gen_addr_reg_index(ctx, t0);
5427
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5428
    tcg_temp_free(t0);
5429 5430 5431
#endif
}

B
Blue Swirl 已提交
5432
static void gen_rfsvc(DisasContext *ctx)
5433 5434
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5435
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5436
#else
A
aurel32 已提交
5437
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5438
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5439 5440
        return;
    }
5441
    gen_helper_rfsvc(cpu_env);
A
aurel32 已提交
5442
    gen_sync_exception(ctx);
5443 5444 5445 5446 5447 5448 5449 5450 5451
#endif
}

/* svc is not implemented for now */

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

/* lfq */
B
Blue Swirl 已提交
5452
static void gen_lfq(DisasContext *ctx)
5453
{
5454
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5455 5456 5457 5458 5459 5460 5461
    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);
5462
    tcg_temp_free(t0);
5463 5464 5465
}

/* lfqu */
B
Blue Swirl 已提交
5466
static void gen_lfqu(DisasContext *ctx)
5467 5468
{
    int ra = rA(ctx->opcode);
5469
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5470 5471 5472 5473 5474 5475 5476 5477
    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);
5478
    if (ra != 0)
5479 5480 5481
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5482 5483 5484
}

/* lfqux */
B
Blue Swirl 已提交
5485
static void gen_lfqux(DisasContext *ctx)
5486 5487
{
    int ra = rA(ctx->opcode);
5488
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5489 5490 5491 5492 5493 5494 5495 5496 5497
    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);
5498
    if (ra != 0)
5499 5500
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5501 5502 5503
}

/* lfqx */
B
Blue Swirl 已提交
5504
static void gen_lfqx(DisasContext *ctx)
5505
{
5506
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5507 5508 5509 5510 5511 5512 5513
    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);
5514
    tcg_temp_free(t0);
5515 5516 5517
}

/* stfq */
B
Blue Swirl 已提交
5518
static void gen_stfq(DisasContext *ctx)
5519
{
5520
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5521 5522 5523 5524 5525 5526 5527
    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);
5528
    tcg_temp_free(t0);
5529 5530 5531
}

/* stfqu */
B
Blue Swirl 已提交
5532
static void gen_stfqu(DisasContext *ctx)
5533 5534
{
    int ra = rA(ctx->opcode);
5535
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5536 5537 5538 5539 5540 5541 5542 5543 5544
    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);
5545
    if (ra != 0)
5546 5547
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5548 5549 5550
}

/* stfqux */
B
Blue Swirl 已提交
5551
static void gen_stfqux(DisasContext *ctx)
5552 5553
{
    int ra = rA(ctx->opcode);
5554
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5555 5556 5557 5558 5559 5560 5561 5562 5563
    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);
5564
    if (ra != 0)
5565 5566
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5567 5568 5569
}

/* stfqx */
B
Blue Swirl 已提交
5570
static void gen_stfqx(DisasContext *ctx)
5571
{
5572
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5573 5574 5575 5576 5577 5578 5579
    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);
5580
    tcg_temp_free(t0);
5581 5582 5583
}

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

5585
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5586
static void gen_mfapidi(DisasContext *ctx)
5587 5588
{
    /* XXX: TODO */
A
aurel32 已提交
5589
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5590 5591
}

5592
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5593
static void gen_tlbiva(DisasContext *ctx)
5594 5595
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5596
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5597
#else
5598
    TCGv t0;
A
aurel32 已提交
5599
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5600
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5601 5602
        return;
    }
5603
    t0 = tcg_temp_new();
A
aurel32 已提交
5604
    gen_addr_reg_index(ctx, t0);
5605
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5606
    tcg_temp_free(t0);
5607 5608 5609 5610
#endif
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5611 5612
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5613
{
5614 5615
    TCGv t0, t1;

P
pbrook 已提交
5616 5617
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5618

5619 5620 5621 5622 5623 5624 5625
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5626 5627 5628
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5629 5630 5631 5632 5633
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5634 5635 5636
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5637 5638 5639 5640 5641 5642 5643
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5644 5645 5646 5647
        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);
5648 5649 5650 5651 5652
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5653 5654 5655 5656
        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);
5657 5658 5659 5660 5661 5662 5663
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5664 5665
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5666 5667 5668 5669 5670
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5671 5672
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5673 5674 5675
        break;
    }
    if (opc2 & 0x04) {
5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691
        /* (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 */
5692
                tcg_gen_movi_tl(cpu_ov, 0);
5693 5694 5695 5696 5697 5698 5699
            }
            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 已提交
5700
                if (opc3 & 0x02) {
5701 5702 5703 5704 5705 5706 5707
                    /* 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 已提交
5708
                if (opc3 & 0x02) {
5709 5710 5711 5712 5713 5714
                    /* Saturate */
                    tcg_gen_movi_tl(t0, UINT32_MAX);
                }
            }
            if (opc3 & 0x10) {
                /* Check overflow */
5715 5716
                tcg_gen_movi_tl(cpu_ov, 1);
                tcg_gen_movi_tl(cpu_so, 1);
5717 5718 5719 5720 5721 5722
            }
            gen_set_label(l1);
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
        }
    } else {
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5723
    }
5724 5725
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5726 5727
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5728
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5729 5730 5731
    }
}

5732
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5733
static void glue(gen_, name)(DisasContext *ctx)                               \
5734 5735 5736 5737 5738 5739
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5740
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5741
/* macchwo   - macchwo.   */
5742
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5743
/* macchws   - macchws.   */
5744
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5745
/* macchwso  - macchwso.  */
5746
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5747
/* macchwsu  - macchwsu.  */
5748
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5749
/* macchwsuo - macchwsuo. */
5750
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5751
/* macchwu   - macchwu.   */
5752
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5753
/* macchwuo  - macchwuo.  */
5754
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5755
/* machhw    - machhw.    */
5756
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5757
/* machhwo   - machhwo.   */
5758
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5759
/* machhws   - machhws.   */
5760
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5761
/* machhwso  - machhwso.  */
5762
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5763
/* machhwsu  - machhwsu.  */
5764
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5765
/* machhwsuo - machhwsuo. */
5766
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5767
/* machhwu   - machhwu.   */
5768
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5769
/* machhwuo  - machhwuo.  */
5770
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5771
/* maclhw    - maclhw.    */
5772
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5773
/* maclhwo   - maclhwo.   */
5774
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5775
/* maclhws   - maclhws.   */
5776
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5777
/* maclhwso  - maclhwso.  */
5778
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5779
/* maclhwu   - maclhwu.   */
5780
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5781
/* maclhwuo  - maclhwuo.  */
5782
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5783
/* maclhwsu  - maclhwsu.  */
5784
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5785
/* maclhwsuo - maclhwsuo. */
5786
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5787
/* nmacchw   - nmacchw.   */
5788
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5789
/* nmacchwo  - nmacchwo.  */
5790
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5791
/* nmacchws  - nmacchws.  */
5792
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5793
/* nmacchwso - nmacchwso. */
5794
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5795
/* nmachhw   - nmachhw.   */
5796
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5797
/* nmachhwo  - nmachhwo.  */
5798
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5799
/* nmachhws  - nmachhws.  */
5800
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5801
/* nmachhwso - nmachhwso. */
5802
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5803
/* nmaclhw   - nmaclhw.   */
5804
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5805
/* nmaclhwo  - nmaclhwo.  */
5806
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5807
/* nmaclhws  - nmaclhws.  */
5808
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5809
/* nmaclhwso - nmaclhwso. */
5810
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5811 5812

/* mulchw  - mulchw.  */
5813
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5814
/* mulchwu - mulchwu. */
5815
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5816
/* mulhhw  - mulhhw.  */
5817
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5818
/* mulhhwu - mulhhwu. */
5819
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5820
/* mullhw  - mullhw.  */
5821
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5822
/* mullhwu - mullhwu. */
5823
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5824 5825

/* mfdcr */
B
Blue Swirl 已提交
5826
static void gen_mfdcr(DisasContext *ctx)
5827 5828
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5829
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5830
#else
5831
    TCGv dcrn;
A
aurel32 已提交
5832
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5833
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5834 5835
        return;
    }
5836 5837 5838
    /* 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));
5839
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
5840
    tcg_temp_free(dcrn);
5841 5842 5843 5844
#endif
}

/* mtdcr */
B
Blue Swirl 已提交
5845
static void gen_mtdcr(DisasContext *ctx)
5846 5847
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5848
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5849
#else
5850
    TCGv dcrn;
A
aurel32 已提交
5851
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5852
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5853 5854
        return;
    }
5855 5856 5857
    /* 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));
5858
    gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
5859
    tcg_temp_free(dcrn);
5860 5861 5862 5863
#endif
}

/* mfdcrx */
5864
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5865
static void gen_mfdcrx(DisasContext *ctx)
5866 5867
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5868
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5869
#else
A
aurel32 已提交
5870
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5871
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5872 5873
        return;
    }
5874 5875
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5876 5877
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5878
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5879 5880 5881 5882
#endif
}

/* mtdcrx */
5883
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5884
static void gen_mtdcrx(DisasContext *ctx)
5885 5886
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5887
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5888
#else
A
aurel32 已提交
5889
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5890
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5891 5892
        return;
    }
5893 5894
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5895 5896
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
5897
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5898 5899 5900
#endif
}

5901
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5902
static void gen_mfdcrux(DisasContext *ctx)
5903
{
5904 5905
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5906 5907
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5908 5909 5910 5911
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5912
static void gen_mtdcrux(DisasContext *ctx)
5913
{
5914 5915
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
5916
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
5917
                         cpu_gpr[rS(ctx->opcode)]);
5918 5919 5920
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5921
/* dccci */
B
Blue Swirl 已提交
5922
static void gen_dccci(DisasContext *ctx)
5923 5924
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5925
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5926
#else
A
aurel32 已提交
5927
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5928
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5929 5930 5931 5932 5933 5934 5935
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
B
Blue Swirl 已提交
5936
static void gen_dcread(DisasContext *ctx)
5937 5938
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5939
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5940
#else
A
aurel32 已提交
5941
    TCGv EA, val;
A
aurel32 已提交
5942
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5943
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5944 5945
        return;
    }
A
aurel32 已提交
5946
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5947
    EA = tcg_temp_new();
A
aurel32 已提交
5948
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5949
    val = tcg_temp_new();
A
aurel32 已提交
5950
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5951 5952 5953
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5954 5955 5956 5957
#endif
}

/* icbt */
B
Blue Swirl 已提交
5958
static void gen_icbt_40x(DisasContext *ctx)
5959 5960 5961 5962 5963 5964 5965 5966
{
    /* 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 已提交
5967
static void gen_iccci(DisasContext *ctx)
5968 5969
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5970
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5971
#else
A
aurel32 已提交
5972
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5973
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5974 5975 5976 5977 5978 5979 5980
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
B
Blue Swirl 已提交
5981
static void gen_icread(DisasContext *ctx)
5982 5983
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5984
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5985
#else
A
aurel32 已提交
5986
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5987
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5988 5989 5990 5991 5992 5993
        return;
    }
    /* interpreted as no-op */
#endif
}

A
aurel32 已提交
5994
/* rfci (mem_idx only) */
B
Blue Swirl 已提交
5995
static void gen_rfci_40x(DisasContext *ctx)
5996 5997
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5998
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5999
#else
A
aurel32 已提交
6000
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6001
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6002 6003 6004
        return;
    }
    /* Restore CPU state */
6005
    gen_helper_40x_rfci(cpu_env);
A
aurel32 已提交
6006
    gen_sync_exception(ctx);
6007 6008 6009
#endif
}

B
Blue Swirl 已提交
6010
static void gen_rfci(DisasContext *ctx)
6011 6012
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6013
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6014
#else
A
aurel32 已提交
6015
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6016
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6017 6018 6019
        return;
    }
    /* Restore CPU state */
6020
    gen_helper_rfci(cpu_env);
A
aurel32 已提交
6021
    gen_sync_exception(ctx);
6022 6023 6024 6025
#endif
}

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

6027
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
6028
static void gen_rfdi(DisasContext *ctx)
6029 6030
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6031
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6032
#else
A
aurel32 已提交
6033
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6034
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6035 6036 6037
        return;
    }
    /* Restore CPU state */
6038
    gen_helper_rfdi(cpu_env);
A
aurel32 已提交
6039
    gen_sync_exception(ctx);
6040 6041 6042
#endif
}

6043
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
6044
static void gen_rfmci(DisasContext *ctx)
6045 6046
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6047
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6048
#else
A
aurel32 已提交
6049
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6050
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6051 6052 6053
        return;
    }
    /* Restore CPU state */
6054
    gen_helper_rfmci(cpu_env);
A
aurel32 已提交
6055
    gen_sync_exception(ctx);
6056 6057
#endif
}
6058

6059
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
6060

6061
/* tlbre */
B
Blue Swirl 已提交
6062
static void gen_tlbre_40x(DisasContext *ctx)
6063 6064
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6065
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6066
#else
A
aurel32 已提交
6067
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6068
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6069 6070 6071 6072
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
6073 6074
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
6075 6076
        break;
    case 1:
6077 6078
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
6079 6080
        break;
    default:
A
aurel32 已提交
6081
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6082
        break;
6083
    }
6084 6085 6086
#endif
}

6087
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
6088
static void gen_tlbsx_40x(DisasContext *ctx)
6089 6090
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6091
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6092
#else
6093
    TCGv t0;
A
aurel32 已提交
6094
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6095
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6096 6097
        return;
    }
6098
    t0 = tcg_temp_new();
A
aurel32 已提交
6099
    gen_addr_reg_index(ctx, t0);
6100
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6101 6102 6103
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
6104
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6105 6106 6107 6108
        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);
    }
6109
#endif
B
bellard 已提交
6110 6111
}

6112
/* tlbwe */
B
Blue Swirl 已提交
6113
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
6114
{
6115
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6116
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6117
#else
A
aurel32 已提交
6118
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6119
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6120 6121 6122 6123
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
6124 6125
        gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
6126 6127
        break;
    case 1:
6128 6129
        gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
6130 6131
        break;
    default:
A
aurel32 已提交
6132
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6133
        break;
6134
    }
6135 6136 6137
#endif
}

6138
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
6139

6140
/* tlbre */
B
Blue Swirl 已提交
6141
static void gen_tlbre_440(DisasContext *ctx)
6142 6143
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6144
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6145
#else
A
aurel32 已提交
6146
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6147
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6148 6149 6150 6151 6152 6153
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6154 6155
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6156 6157
            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                 t0, cpu_gpr[rA(ctx->opcode)]);
6158 6159
            tcg_temp_free_i32(t0);
        }
6160 6161
        break;
    default:
A
aurel32 已提交
6162
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6163 6164 6165 6166 6167 6168
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
6169
static void gen_tlbsx_440(DisasContext *ctx)
6170 6171
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6172
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6173
#else
6174
    TCGv t0;
A
aurel32 已提交
6175
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6176
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6177 6178
        return;
    }
6179
    t0 = tcg_temp_new();
A
aurel32 已提交
6180
    gen_addr_reg_index(ctx, t0);
6181
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6182 6183 6184
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
6185
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6186 6187 6188 6189
        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);
    }
6190 6191 6192 6193
#endif
}

/* tlbwe */
B
Blue Swirl 已提交
6194
static void gen_tlbwe_440(DisasContext *ctx)
6195 6196
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6197
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6198
#else
A
aurel32 已提交
6199
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6200
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6201 6202 6203 6204 6205 6206
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6207 6208
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6209 6210
            gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
                                 cpu_gpr[rS(ctx->opcode)]);
6211 6212
            tcg_temp_free_i32(t0);
        }
6213 6214
        break;
    default:
A
aurel32 已提交
6215
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6216 6217 6218 6219 6220
        break;
    }
#endif
}

A
Alexander Graf 已提交
6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233
/* 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;
    }

6234
    gen_helper_booke206_tlbre(cpu_env);
A
Alexander Graf 已提交
6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257
#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)]);
6258
    gen_helper_booke206_tlbsx(cpu_env, t0);
A
Alexander Graf 已提交
6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271
#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;
    }
6272
    gen_update_nip(ctx, ctx->nip - 4);
6273
    gen_helper_booke206_tlbwe(cpu_env);
A
Alexander Graf 已提交
6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290
#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);

6291
    gen_helper_booke206_tlbivax(cpu_env, t0);
A
Alexander Graf 已提交
6292 6293 6294
#endif
}

A
Alexander Graf 已提交
6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310
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:
6311
        gen_helper_booke206_tlbilx0(cpu_env, t0);
A
Alexander Graf 已提交
6312 6313
        break;
    case 1:
6314
        gen_helper_booke206_tlbilx1(cpu_env, t0);
A
Alexander Graf 已提交
6315 6316
        break;
    case 3:
6317
        gen_helper_booke206_tlbilx3(cpu_env, t0);
A
Alexander Graf 已提交
6318 6319 6320 6321 6322 6323 6324 6325 6326 6327
        break;
    default:
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        break;
    }

    tcg_temp_free(t0);
#endif
}

A
Alexander Graf 已提交
6328

6329
/* wrtee */
B
Blue Swirl 已提交
6330
static void gen_wrtee(DisasContext *ctx)
6331 6332
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6333
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6334
#else
6335
    TCGv t0;
A
aurel32 已提交
6336
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6337
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6338 6339
        return;
    }
6340 6341 6342 6343 6344
    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 已提交
6345 6346 6347
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
6348
    gen_stop_exception(ctx);
6349 6350 6351 6352
#endif
}

/* wrteei */
B
Blue Swirl 已提交
6353
static void gen_wrteei(DisasContext *ctx)
6354 6355
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6356
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6357
#else
A
aurel32 已提交
6358
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6359
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6360 6361
        return;
    }
6362
    if (ctx->opcode & 0x00008000) {
6363 6364
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6365
        gen_stop_exception(ctx);
6366
    } else {
A
aurel32 已提交
6367
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6368
    }
6369 6370 6371
#endif
}

J
j_mayer 已提交
6372
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
6373

6374
/* dlmzb */
B
Blue Swirl 已提交
6375
static void gen_dlmzb(DisasContext *ctx)
6376
{
6377
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6378 6379
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
6380
    tcg_temp_free_i32(t0);
6381 6382 6383
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
6384
static void gen_mbar(DisasContext *ctx)
6385 6386 6387 6388 6389
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
A
Alexander Graf 已提交
6390
static void gen_msync_4xx(DisasContext *ctx)
6391 6392 6393 6394 6395
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6396
static void gen_icbt_440(DisasContext *ctx)
6397 6398 6399 6400 6401
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6402 6403
}

A
Alexander Graf 已提交
6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415
/* 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;
    }

6416
    gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
A
Alexander Graf 已提交
6417 6418 6419
#endif
}

A
Alexander Graf 已提交
6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433
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
}

6434 6435 6436
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

B
Blue Swirl 已提交
6437
static inline TCGv_ptr gen_avr_ptr(int reg)
A
aurel32 已提交
6438
{
A
aurel32 已提交
6439
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6440 6441 6442 6443
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

6444
#define GEN_VR_LDX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6445
static void glue(gen_, name)(DisasContext *ctx)                                       \
6446
{                                                                             \
6447
    TCGv EA;                                                                  \
6448
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6449
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6450 6451
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6452
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6453
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6454
    gen_addr_reg_index(ctx, EA);                                              \
6455
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6456 6457
    if (ctx->le_mode) {                                                       \
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6458
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6459
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6460
    } else {                                                                  \
A
aurel32 已提交
6461
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6462
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6463
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6464 6465
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6466 6467 6468
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
B
Blue Swirl 已提交
6469
static void gen_st##name(DisasContext *ctx)                                   \
6470
{                                                                             \
6471
    TCGv EA;                                                                  \
6472
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6473
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6474 6475
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6476
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6477
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6478
    gen_addr_reg_index(ctx, EA);                                              \
6479
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6480 6481
    if (ctx->le_mode) {                                                       \
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6482
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6483
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6484
    } else {                                                                  \
A
aurel32 已提交
6485
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6486
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6487
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6488 6489
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6490 6491
}

A
aurel32 已提交
6492
#define GEN_VR_LVE(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6493
static void gen_lve##name(DisasContext *ctx)                            \
A
aurel32 已提交
6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504
    {                                                                   \
        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));                              \
6505
        gen_helper_lve##name(cpu_env, rs, EA);                          \
A
aurel32 已提交
6506 6507 6508 6509 6510
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

#define GEN_VR_STVE(name, opc2, opc3)                                   \
B
Blue Swirl 已提交
6511
static void gen_stve##name(DisasContext *ctx)                           \
A
aurel32 已提交
6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522
    {                                                                   \
        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));                              \
6523
        gen_helper_stve##name(cpu_env, rs, EA);                         \
A
aurel32 已提交
6524 6525 6526 6527
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

6528
GEN_VR_LDX(lvx, 0x07, 0x03);
6529
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6530
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6531

A
aurel32 已提交
6532 6533 6534 6535
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6536
GEN_VR_STX(svx, 0x07, 0x07);
6537
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6538
GEN_VR_STX(svxl, 0x07, 0x0F);
6539

A
aurel32 已提交
6540 6541 6542 6543
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

B
Blue Swirl 已提交
6544
static void gen_lvsl(DisasContext *ctx)
A
aurel32 已提交
6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559
{
    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 已提交
6560
static void gen_lvsr(DisasContext *ctx)
A
aurel32 已提交
6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575
{
    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 已提交
6576
static void gen_mfvscr(DisasContext *ctx)
6577 6578 6579 6580 6581 6582 6583 6584
{
    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();
6585
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
6586
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6587
    tcg_temp_free_i32(t);
6588 6589
}

B
Blue Swirl 已提交
6590
static void gen_mtvscr(DisasContext *ctx)
6591
{
A
aurel32 已提交
6592
    TCGv_ptr p;
6593 6594 6595 6596
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6597
    p = gen_avr_ptr(rD(ctx->opcode));
6598
    gen_helper_mtvscr(cpu_env, p);
A
aurel32 已提交
6599
    tcg_temp_free_ptr(p);
6600 6601
}

6602 6603
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
B
Blue Swirl 已提交
6604
static void glue(gen_, name)(DisasContext *ctx)                                 \
6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619
{                                                                       \
    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);

6620
#define GEN_VXFORM(name, opc2, opc3)                                    \
B
Blue Swirl 已提交
6621
static void glue(gen_, name)(DisasContext *ctx)                                 \
6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636
{                                                                       \
    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);                                              \
}

6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647
#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));                                  \
6648
    gen_helper_##name(cpu_env, rd, ra, rb);                             \
6649 6650 6651 6652 6653
    tcg_temp_free_ptr(ra);                                              \
    tcg_temp_free_ptr(rb);                                              \
    tcg_temp_free_ptr(rd);                                              \
}

A
aurel32 已提交
6654 6655 6656 6657 6658 6659
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);
6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671
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 已提交
6672 6673 6674 6675 6676 6677
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 已提交
6678 6679 6680 6681 6682 6683
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 已提交
6684 6685 6686 6687 6688 6689 6690 6691
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 已提交
6692 6693 6694
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6695 6696 6697 6698 6699 6700
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 已提交
6701 6702
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6703 6704
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716
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 已提交
6717 6718 6719
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6720 6721
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6722 6723 6724 6725 6726 6727 6728 6729
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 已提交
6730
GEN_VXFORM(vpkpx, 7, 12);
6731 6732 6733 6734 6735 6736 6737 6738 6739
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 已提交
6740

6741
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
B
Blue Swirl 已提交
6742
static void glue(gen_, name)(DisasContext *ctx)                         \
6743 6744 6745 6746 6747 6748 6749 6750 6751
    {                                                                   \
        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));                              \
6752
        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
6753 6754 6755 6756 6757 6758 6759 6760 6761
        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)))

6762 6763 6764 6765 6766 6767 6768 6769 6770
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)
6771 6772 6773 6774
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6775

A
aurel32 已提交
6776
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6777
static void glue(gen_, name)(DisasContext *ctx)                         \
A
aurel32 已提交
6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795
    {                                                                   \
        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);

6796
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
B
Blue Swirl 已提交
6797
static void glue(gen_, name)(DisasContext *ctx)                                 \
6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810
    {                                                                   \
        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);                                         \
    }

6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826
#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 已提交
6827 6828 6829 6830
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 已提交
6831 6832
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
6833 6834 6835 6836 6837 6838 6839 6840
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 已提交
6841

6842
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6843
static void glue(gen_, name)(DisasContext *ctx)                                 \
6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857
    {                                                                   \
        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);                                          \
    }

6858
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
B
Blue Swirl 已提交
6859
static void glue(gen_, name)(DisasContext *ctx)                                 \
6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875
    {                                                                   \
        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);                                          \
    }

6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894
#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 已提交
6895 6896 6897
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
6898 6899 6900 6901
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 已提交
6902

B
Blue Swirl 已提交
6903
static void gen_vsldoi(DisasContext *ctx)
A
aurel32 已提交
6904 6905
{
    TCGv_ptr ra, rb, rd;
6906
    TCGv_i32 sh;
A
aurel32 已提交
6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918
    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);
6919
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6920 6921
}

6922
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
6923
static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934
    {                                                                   \
        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)) {                                          \
6935
            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
6936
        } else {                                                        \
6937
            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
6938 6939 6940 6941 6942 6943 6944
        }                                                               \
        tcg_temp_free_ptr(ra);                                          \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rc);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6945 6946
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

B
Blue Swirl 已提交
6947
static void gen_vmladduhm(DisasContext *ctx)
A
aurel32 已提交
6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964
{
    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 已提交
6965
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6966
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6967
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6968
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6969
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6970

6971 6972
/***                           SPE extension                               ***/
/* Register moves */
6973

6974 6975 6976 6977 6978

static inline void gen_evmra(DisasContext *ctx)
{

    if (unlikely(!ctx->spe_enabled)) {
6979
        gen_exception(ctx, POWERPC_EXCP_SPEU);
6980 6981 6982 6983 6984 6985 6986 6987 6988 6989
        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,
6990
                   offsetof(CPUPPCState, spe_acc));
6991 6992 6993 6994 6995 6996 6997
#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 */
6998
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
6999 7000 7001 7002 7003 7004 7005 7006
    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 已提交
7007 7008
static inline void gen_load_gpr64(TCGv_i64 t, int reg)
{
A
aurel32 已提交
7009 7010 7011
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
7012
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
7013
#endif
A
aurel32 已提交
7014
}
7015

B
Blue Swirl 已提交
7016 7017
static inline void gen_store_gpr64(int reg, TCGv_i64 t)
{
A
aurel32 已提交
7018 7019 7020
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
7021
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
7022 7023 7024
    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 已提交
7025
    tcg_temp_free_i64(tmp);
7026
#endif
A
aurel32 已提交
7027
}
7028

7029
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type)         \
B
Blue Swirl 已提交
7030
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
7031 7032 7033 7034 7035 7036 7037 7038
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
B
Blue Swirl 已提交
7039
static inline void gen_speundef(DisasContext *ctx)
7040
{
A
aurel32 已提交
7041
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
7042 7043
}

7044 7045 7046
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
B
Blue Swirl 已提交
7047
static inline void gen_##name(DisasContext *ctx)                              \
7048 7049
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7050
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7051 7052
        return;                                                               \
    }                                                                         \
7053 7054 7055 7056 7057
    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 已提交
7058
static inline void gen_##name(DisasContext *ctx)                              \
7059 7060
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7061
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7062 7063 7064 7065 7066 7067
        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)]);                                        \
7068
}
7069 7070 7071 7072 7073 7074 7075 7076 7077 7078
#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);
7079

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

7121 7122 7123
/* SPE arithmetic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
7124
static inline void gen_##name(DisasContext *ctx)                              \
7125 7126
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7127
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7128 7129
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7130 7131 7132
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7133 7134 7135 7136
    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 已提交
7137
    tcg_temp_free_i64(t2);                                                    \
7138 7139
    tcg_op(t1, t1);                                                           \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7140 7141
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7142
}
7143
#else
P
pbrook 已提交
7144
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
B
Blue Swirl 已提交
7145
static inline void gen_##name(DisasContext *ctx)                              \
7146 7147
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7148
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7149 7150 7151 7152 7153 7154
        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
7155

B
Blue Swirl 已提交
7156
static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
7157 7158 7159
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
7160

7161 7162 7163 7164
    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 已提交
7165
    tcg_gen_mov_i32(ret, arg1);
7166 7167 7168 7169 7170 7171
    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 已提交
7172
static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
7173
{
7174 7175 7176 7177
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
7178 7179
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
7180

7181 7182
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
B
Blue Swirl 已提交
7183
static inline void gen_##name(DisasContext *ctx)                              \
7184 7185
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7186
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7187 7188
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7189 7190 7191
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
7192
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
7193 7194 7195 7196 7197 7198 7199
    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 已提交
7200
    tcg_temp_free_i64(t3);                                                    \
7201
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
7202
    tcg_temp_free_i32(t2);                                                    \
7203
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7204 7205
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7206
}
7207 7208
#else
#define GEN_SPEOP_ARITH2(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;                                                               \
    }                                                                         \
7215 7216 7217 7218
    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)]);                                        \
7219
}
7220
#endif
7221

B
Blue Swirl 已提交
7222
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7223
{
P
pbrook 已提交
7224
    TCGv_i32 t0;
7225
    int l1, l2;
7226

7227 7228
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7229
    t0 = tcg_temp_local_new_i32();
7230 7231 7232 7233 7234 7235 7236
    /* 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);
7237
    gen_set_label(l2);
P
pbrook 已提交
7238
    tcg_temp_free_i32(t0);
7239 7240
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
B
Blue Swirl 已提交
7241
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7242
{
P
pbrook 已提交
7243
    TCGv_i32 t0;
7244 7245 7246 7247
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7248
    t0 = tcg_temp_local_new_i32();
7249 7250 7251 7252 7253 7254 7255
    /* 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);
7256
    gen_set_label(l2);
P
pbrook 已提交
7257
    tcg_temp_free_i32(t0);
7258 7259
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
B
Blue Swirl 已提交
7260
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7261
{
P
pbrook 已提交
7262
    TCGv_i32 t0;
7263 7264 7265 7266
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
7267
    t0 = tcg_temp_local_new_i32();
7268 7269 7270 7271 7272 7273 7274
    /* 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);
7275
    gen_set_label(l2);
P
pbrook 已提交
7276
    tcg_temp_free_i32(t0);
7277 7278
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
B
Blue Swirl 已提交
7279
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7280
{
P
pbrook 已提交
7281
    TCGv_i32 t0 = tcg_temp_new_i32();
7282 7283
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
7284
    tcg_temp_free_i32(t0);
7285 7286
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
B
Blue Swirl 已提交
7287
static inline void gen_evmergehi(DisasContext *ctx)
7288 7289
{
    if (unlikely(!ctx->spe_enabled)) {
7290
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7291 7292 7293
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7294 7295
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306
    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 已提交
7307
static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
7308
{
7309 7310 7311
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
7312

7313 7314 7315
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7316
static inline void gen_##name(DisasContext *ctx)                              \
7317 7318
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7319
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7320 7321
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
7322 7323 7324
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7325 7326 7327 7328
    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 已提交
7329
    tcg_temp_free_i64(t2);                                                    \
7330 7331
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
7332 7333
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7334 7335 7336
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
B
Blue Swirl 已提交
7337
static inline void gen_##name(DisasContext *ctx)                              \
7338 7339
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7340
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354
        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 已提交
7355
static inline void gen_##name(DisasContext *ctx)                              \
7356 7357
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7358
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7359 7360 7361 7362 7363 7364
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
7365 7366 7367
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
7368 7369 7370
    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 已提交
7371
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
7372 7373 7374 7375 7376 7377 7378 7379 7380
    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 已提交
7381
    tcg_temp_free_i64(t2);                                                    \
7382 7383 7384 7385 7386 7387 7388 7389
    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 已提交
7390 7391
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
7392 7393 7394
}
#else
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
B
Blue Swirl 已提交
7395
static inline void gen_##name(DisasContext *ctx)                              \
7396 7397
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
7398
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431
        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 已提交
7432
static inline void gen_brinc(DisasContext *ctx)
7433 7434
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
7435 7436
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7437
}
B
Blue Swirl 已提交
7438
static inline void gen_evmergelo(DisasContext *ctx)
7439 7440
{
    if (unlikely(!ctx->spe_enabled)) {
7441
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7442 7443 7444
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7445 7446
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7447
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7448 7449 7450 7451 7452 7453
    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)]);
7454
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7455 7456
#endif
}
B
Blue Swirl 已提交
7457
static inline void gen_evmergehilo(DisasContext *ctx)
7458 7459
{
    if (unlikely(!ctx->spe_enabled)) {
7460
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7461 7462 7463
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7464 7465
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7466
    tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
7467 7468 7469 7470 7471 7472 7473 7474 7475
    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 已提交
7476
static inline void gen_evmergelohi(DisasContext *ctx)
7477 7478
{
    if (unlikely(!ctx->spe_enabled)) {
7479
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7480 7481 7482
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7483 7484
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7485 7486 7487 7488 7489 7490
    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
7491 7492 7493 7494 7495 7496 7497 7498 7499 7500
    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)]);
    }
7501 7502
#endif
}
B
Blue Swirl 已提交
7503
static inline void gen_evsplati(DisasContext *ctx)
7504
{
7505
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
7506

7507
#if defined(TARGET_PPC64)
7508
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7509 7510 7511 7512 7513
#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 已提交
7514
static inline void gen_evsplatfi(DisasContext *ctx)
7515
{
7516
    uint64_t imm = rA(ctx->opcode) << 27;
7517

7518
#if defined(TARGET_PPC64)
7519
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7520 7521 7522 7523
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7524 7525
}

B
Blue Swirl 已提交
7526
static inline void gen_evsel(DisasContext *ctx)
7527 7528 7529 7530 7531
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7532
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7533
#if defined(TARGET_PPC64)
P
pbrook 已提交
7534 7535
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554
#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)
7555
    tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
7556 7557 7558 7559 7560 7561
#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)
7562
    tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
7563 7564 7565 7566
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7567
    tcg_temp_free_i32(t0);
7568 7569 7570 7571 7572 7573
#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 已提交
7574 7575

static void gen_evsel0(DisasContext *ctx)
7576 7577 7578
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7579 7580

static void gen_evsel1(DisasContext *ctx)
7581 7582 7583
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7584 7585

static void gen_evsel2(DisasContext *ctx)
7586 7587 7588
{
    gen_evsel(ctx);
}
B
Blue Swirl 已提交
7589 7590

static void gen_evsel3(DisasContext *ctx)
7591 7592 7593
{
    gen_evsel(ctx);
}
7594

7595 7596 7597 7598 7599 7600 7601
/* Multiply */

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

    if (unlikely(!ctx->spe_enabled)) {
7602
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630
        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)) {
7631
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7632 7633 7634 7635 7636 7637 7638 7639 7640
        return;
    }

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

    tmp = tcg_temp_new_i64();

    /* acc := rD */
    gen_load_gpr64(tmp, rD(ctx->opcode));
7641
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7642 7643 7644 7645 7646 7647 7648 7649 7650
    tcg_temp_free_i64(tmp);
}

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

    if (unlikely(!ctx->spe_enabled)) {
7651
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663
        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 */
7664
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7665 7666 7667 7668 7669

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

    /* Store acc */
7670
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683

    /* 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)) {
7684
        gen_exception(ctx, POWERPC_EXCP_SPEU);
7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717
        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));
7718
    tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736

    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 */
7737
    tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7738 7739 7740 7741 7742

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

    /* Store acc */
7743
    tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
7744 7745 7746 7747 7748 7749 7750 7751

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

    tcg_temp_free_i64(acc);
    tcg_temp_free_i64(tmp);
}

7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780
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); ////
7781

7782
/* SPE load and stores */
B
Blue Swirl 已提交
7783
static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
7784 7785 7786
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7787
    if (rA(ctx->opcode) == 0) {
7788
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7789
    } else {
7790
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
7791
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
7792 7793 7794
            tcg_gen_ext32u_tl(EA, EA);
        }
    }
7795
}
7796

B
Blue Swirl 已提交
7797
static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7798 7799
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7800
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7801 7802
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7803
    gen_qemu_ld64(ctx, t0, addr);
7804 7805 7806 7807 7808
    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
7809
}
7810

B
Blue Swirl 已提交
7811
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7812
{
7813
#if defined(TARGET_PPC64)
7814
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7815
    gen_qemu_ld32u(ctx, t0, addr);
7816
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7817 7818
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7819 7820 7821
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7822 7823 7824
    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);
7825
#endif
7826
}
7827

B
Blue Swirl 已提交
7828
static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7829 7830 7831
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7832
    gen_qemu_ld16u(ctx, t0, addr);
7833
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7834 7835
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7836 7837
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7838 7839
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7840 7841
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7842 7843
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7844
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7845
#else
A
aurel32 已提交
7846
    gen_qemu_ld16u(ctx, t0, addr);
7847
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7848 7849
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7850
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7851 7852
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7853
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7854 7855
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7856
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7857
#endif
7858
    tcg_temp_free(t0);
7859 7860
}

B
Blue Swirl 已提交
7861
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7862 7863
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7864
    gen_qemu_ld16u(ctx, t0, addr);
7865 7866 7867 7868 7869 7870 7871 7872 7873 7874
#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);
7875 7876
}

B
Blue Swirl 已提交
7877
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7878 7879
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7880
    gen_qemu_ld16u(ctx, t0, addr);
7881 7882 7883 7884 7885 7886 7887 7888
#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);
7889 7890
}

B
Blue Swirl 已提交
7891
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7892 7893
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7894
    gen_qemu_ld16s(ctx, t0, addr);
7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905
#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 已提交
7906
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7907 7908 7909
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7910
    gen_qemu_ld16u(ctx, t0, addr);
7911
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7912 7913
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7914 7915 7916
    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 已提交
7917
    gen_qemu_ld16u(ctx, t0, addr);
7918
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7919 7920
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7921 7922 7923 7924 7925
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
7926
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7927 7928 7929
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7930 7931 7932
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7933 7934 7935 7936
    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 已提交
7937 7938 7939
    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);
7940 7941 7942
#endif
}

B
Blue Swirl 已提交
7943
static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7944 7945 7946
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7947
    gen_qemu_ld16s(ctx, t0, addr);
7948
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7949 7950
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7951 7952 7953 7954
    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 已提交
7955 7956 7957
    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);
7958 7959 7960
#endif
}

B
Blue Swirl 已提交
7961
static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7962 7963
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7964
    gen_qemu_ld32u(ctx, t0, addr);
7965
#if defined(TARGET_PPC64)
7966 7967 7968 7969 7970 7971 7972 7973 7974
    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 已提交
7975
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7976 7977 7978
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7979
    gen_qemu_ld16u(ctx, t0, addr);
7980 7981 7982
    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 已提交
7983 7984
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7985 7986 7987 7988
    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 已提交
7989
    gen_qemu_ld16u(ctx, t0, addr);
7990 7991
    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 已提交
7992 7993
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7994 7995
    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);
7996
#endif
7997 7998 7999
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
8000
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
8001 8002
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
8003
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
8004
#else
8005 8006
    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 已提交
8007
    gen_qemu_st64(ctx, t0, addr);
8008 8009 8010 8011
    tcg_temp_free_i64(t0);
#endif
}

B
Blue Swirl 已提交
8012
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
8013
{
8014
#if defined(TARGET_PPC64)
8015 8016
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
8017
    gen_qemu_st32(ctx, t0, addr);
8018 8019
    tcg_temp_free(t0);
#else
A
aurel32 已提交
8020
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
8021
#endif
A
aurel32 已提交
8022 8023
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
8024 8025
}

B
Blue Swirl 已提交
8026
static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
8027 8028 8029 8030 8031 8032 8033
{
    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 已提交
8034 8035
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
8036 8037
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
8038
    gen_qemu_st16(ctx, t0, addr);
8039
#else
A
aurel32 已提交
8040
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
8041
#endif
A
aurel32 已提交
8042
    gen_addr_add(ctx, addr, addr, 2);
8043
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
8044
    gen_qemu_st16(ctx, t0, addr);
8045
    tcg_temp_free(t0);
A
aurel32 已提交
8046 8047
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
8048 8049
}

B
Blue Swirl 已提交
8050
static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
8051 8052 8053 8054 8055 8056 8057
{
    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 已提交
8058 8059
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
8060
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
8061
    gen_qemu_st16(ctx, t0, addr);
8062 8063 8064
    tcg_temp_free(t0);
}

B
Blue Swirl 已提交
8065
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
8066 8067 8068 8069
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
8070
    gen_qemu_st16(ctx, t0, addr);
8071 8072
    tcg_temp_free(t0);
#else
A
aurel32 已提交
8073
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
8074
#endif
A
aurel32 已提交
8075 8076
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
8077 8078
}

B
Blue Swirl 已提交
8079
static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
8080 8081 8082 8083
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
8084
    gen_qemu_st32(ctx, t0, addr);
8085 8086
    tcg_temp_free(t0);
#else
A
aurel32 已提交
8087
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
8088 8089 8090
#endif
}

B
Blue Swirl 已提交
8091
static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
8092
{
A
aurel32 已提交
8093
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
8094 8095 8096
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
B
Blue Swirl 已提交
8097
static void glue(gen_, name)(DisasContext *ctx)                                       \
8098 8099 8100
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8101
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8102 8103
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8104
    gen_set_access_type(ctx, ACCESS_INT);                                     \
8105 8106
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
8107
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
8108
    } else {                                                                  \
A
aurel32 已提交
8109
        gen_addr_reg_index(ctx, t0);                                          \
8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133
    }                                                                         \
    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);
8134 8135 8136

/* Multiply and add - TODO */
#if 0
8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204
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);
8205 8206 8207
#endif

/***                      SPE floating-point extension                     ***/
A
aurel32 已提交
8208 8209
#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
8210
static inline void gen_##name(DisasContext *ctx)                              \
8211
{                                                                             \
A
aurel32 已提交
8212 8213 8214 8215
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8216
    gen_helper_##name(t0, cpu_env, t0);                                       \
A
aurel32 已提交
8217 8218 8219 8220 8221 8222 8223
    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);                                                        \
8224
}
A
aurel32 已提交
8225
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
8226
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8227 8228 8229 8230
{                                                                             \
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
8231
    gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]);                 \
A
aurel32 已提交
8232 8233 8234 8235 8236 8237 8238 8239 8240
    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 已提交
8241
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8242 8243 8244
{                                                                             \
    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
8245
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);                 \
A
aurel32 已提交
8246 8247 8248
    tcg_temp_free_i32(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
B
Blue Swirl 已提交
8249
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8250
{                                                                             \
8251 8252
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rB(ctx->opcode)]);                              \
A
aurel32 已提交
8253 8254
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
8255
static inline void gen_##name(DisasContext *ctx)                              \
8256
{                                                                             \
A
aurel32 已提交
8257 8258
    TCGv_i32 t0, t1;                                                          \
    TCGv_i64 t2;                                                              \
8259
    if (unlikely(!ctx->spe_enabled)) {                                        \
8260
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8261 8262
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8263 8264 8265 8266
    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)]);                       \
8267
    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
A
aurel32 已提交
8268 8269 8270 8271 8272 8273 8274 8275
    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);                                                        \
8276
}
A
aurel32 已提交
8277
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
8278
static inline void gen_##name(DisasContext *ctx)                              \
8279 8280
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8281
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8282 8283
        return;                                                               \
    }                                                                         \
8284 8285
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
8286
}
A
aurel32 已提交
8287
#define GEN_SPEFPUOP_COMP_32(name)                                            \
B
Blue Swirl 已提交
8288
static inline void gen_##name(DisasContext *ctx)                              \
8289
{                                                                             \
A
aurel32 已提交
8290
    TCGv_i32 t0, t1;                                                          \
8291
    if (unlikely(!ctx->spe_enabled)) {                                        \
8292
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
8293 8294
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
8295 8296 8297 8298
    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)]);                       \
8299
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
A
aurel32 已提交
8300 8301 8302 8303
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
B
Blue Swirl 已提交
8304
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8305 8306
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8307
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8308 8309
        return;                                                               \
    }                                                                         \
8310
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env,                    \
A
aurel32 已提交
8311 8312 8313 8314
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#else
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
B
Blue Swirl 已提交
8315
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8316
{                                                                             \
8317 8318
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                      cpu_gpr[rB(ctx->opcode)]);                              \
8319
}
A
aurel32 已提交
8320
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
B
Blue Swirl 已提交
8321
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8322 8323 8324
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
8325
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);                 \
A
aurel32 已提交
8326 8327 8328
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
B
Blue Swirl 已提交
8329
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8330 8331
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
8332
    gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]);                 \
A
aurel32 已提交
8333 8334 8335 8336
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
B
Blue Swirl 已提交
8337
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8338 8339 8340
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
8341
    gen_helper_##name(t0, cpu_env, t0);                                       \
A
aurel32 已提交
8342 8343 8344 8345
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
B
Blue Swirl 已提交
8346
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8347 8348
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8349
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8350 8351
        return;                                                               \
    }                                                                         \
8352
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
A
aurel32 已提交
8353 8354 8355
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
B
Blue Swirl 已提交
8356
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8357 8358 8359
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8360
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8361 8362 8363 8364 8365 8366
        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));                                      \
8367
    gen_helper_##name(t0, cpu_env, t0, t1);                                   \
A
aurel32 已提交
8368 8369 8370 8371 8372
    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 已提交
8373
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8374 8375
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8376
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8377 8378
        return;                                                               \
    }                                                                         \
8379
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env,                    \
A
aurel32 已提交
8380 8381 8382
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
B
Blue Swirl 已提交
8383
static inline void gen_##name(DisasContext *ctx)                              \
A
aurel32 已提交
8384 8385 8386
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
8387
        gen_exception(ctx, POWERPC_EXCP_SPEU);                                \
A
aurel32 已提交
8388 8389 8390 8391 8392 8393
        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));                                      \
8394
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1);           \
A
aurel32 已提交
8395 8396 8397 8398
    tcg_temp_free_i64(t0);                                                    \
    tcg_temp_free_i64(t1);                                                    \
}
#endif
8399

8400 8401
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
8402 8403 8404 8405
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 已提交
8406
static inline void gen_evfsabs(DisasContext *ctx)
A
aurel32 已提交
8407 8408
{
    if (unlikely(!ctx->spe_enabled)) {
8409
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8410 8411 8412
        return;
    }
#if defined(TARGET_PPC64)
8413
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
A
aurel32 已提交
8414
#else
8415 8416
    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 已提交
8417 8418
#endif
}
B
Blue Swirl 已提交
8419
static inline void gen_evfsnabs(DisasContext *ctx)
A
aurel32 已提交
8420 8421
{
    if (unlikely(!ctx->spe_enabled)) {
8422
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8423 8424 8425
        return;
    }
#if defined(TARGET_PPC64)
8426
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8427
#else
8428 8429
    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 已提交
8430 8431
#endif
}
B
Blue Swirl 已提交
8432
static inline void gen_evfsneg(DisasContext *ctx)
A
aurel32 已提交
8433 8434
{
    if (unlikely(!ctx->spe_enabled)) {
8435
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8436 8437 8438
        return;
    }
#if defined(TARGET_PPC64)
8439
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
A
aurel32 已提交
8440
#else
8441 8442
    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 已提交
8443 8444 8445
#endif
}

8446
/* Conversion */
A
aurel32 已提交
8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457
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);

8458
/* Comparison */
A
aurel32 已提交
8459 8460 8461 8462 8463 8464
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);
8465 8466

/* Opcodes definitions */
8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480
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); //
8481 8482 8483

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8484 8485 8486 8487
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 已提交
8488
static inline void gen_efsabs(DisasContext *ctx)
A
aurel32 已提交
8489 8490
{
    if (unlikely(!ctx->spe_enabled)) {
8491
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8492 8493
        return;
    }
8494
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
A
aurel32 已提交
8495
}
B
Blue Swirl 已提交
8496
static inline void gen_efsnabs(DisasContext *ctx)
A
aurel32 已提交
8497 8498
{
    if (unlikely(!ctx->spe_enabled)) {
8499
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8500 8501
        return;
    }
8502
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8503
}
B
Blue Swirl 已提交
8504
static inline void gen_efsneg(DisasContext *ctx)
A
aurel32 已提交
8505 8506
{
    if (unlikely(!ctx->spe_enabled)) {
8507
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8508 8509
        return;
    }
8510
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
A
aurel32 已提交
8511 8512
}

8513
/* Conversion */
A
aurel32 已提交
8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525
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);

8526
/* Comparison */
A
aurel32 已提交
8527 8528 8529 8530 8531 8532
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);
8533 8534

/* Opcodes definitions */
8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548
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); //
8549 8550 8551

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
8552 8553 8554 8555
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 已提交
8556
static inline void gen_efdabs(DisasContext *ctx)
A
aurel32 已提交
8557 8558
{
    if (unlikely(!ctx->spe_enabled)) {
8559
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8560 8561 8562
        return;
    }
#if defined(TARGET_PPC64)
8563
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
A
aurel32 已提交
8564
#else
8565 8566
    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 已提交
8567 8568
#endif
}
B
Blue Swirl 已提交
8569
static inline void gen_efdnabs(DisasContext *ctx)
A
aurel32 已提交
8570 8571
{
    if (unlikely(!ctx->spe_enabled)) {
8572
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8573 8574 8575
        return;
    }
#if defined(TARGET_PPC64)
8576
    tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8577
#else
8578 8579
    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 已提交
8580 8581
#endif
}
B
Blue Swirl 已提交
8582
static inline void gen_efdneg(DisasContext *ctx)
A
aurel32 已提交
8583 8584
{
    if (unlikely(!ctx->spe_enabled)) {
8585
        gen_exception(ctx, POWERPC_EXCP_SPEU);
A
aurel32 已提交
8586 8587 8588
        return;
    }
#if defined(TARGET_PPC64)
8589
    tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
A
aurel32 已提交
8590
#else
8591 8592
    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 已提交
8593 8594 8595
#endif
}

8596
/* Conversion */
A
aurel32 已提交
8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611
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);
8612 8613

/* Comparison */
A
aurel32 已提交
8614 8615 8616 8617 8618 8619
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);
8620 8621

/* Opcodes definitions */
8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637
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); //
8638

A
Anthony Liguori 已提交
8639
static opcode_t opcodes[] = {
8640 8641 8642 8643 8644
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),
8645
GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671
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),
8672
GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
8673
GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
8674
#if defined(TARGET_PPC64)
8675
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
8676
GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
8677
GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697
#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),
8698
GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT),
8699
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
8700 8701
GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT),
GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT),
8702
GEN_HANDLER_E(fcpsgn, 0x3F, 0x08, 0x00, 0x00000000, PPC_NONE, PPC2_ISA205),
8703 8704 8705 8706
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),
8707 8708
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00000000, PPC_FLOAT),
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006e0800, PPC_FLOAT),
8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721
#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),
8722
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
8723 8724
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
8725
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762
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),
A
Alexander Graf 已提交
8763
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779
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),
8780 8781 8782
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),
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
#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 已提交
8863
GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
8864 8865 8866 8867 8868 8869 8870 8871
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 已提交
8872 8873 8874 8875 8876 8877 8878 8879
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 已提交
8880 8881
GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8882 8883
GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
A
Alexander Graf 已提交
8884 8885
GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
8886
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8887
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8888
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
A
Alexander Graf 已提交
8889 8890
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
              PPC_BOOKE, PPC2_BOOKE206),
A
Alexander Graf 已提交
8891
GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
A
Alexander Graf 已提交
8892 8893
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
               PPC_BOOKE, PPC2_BOOKE206),
8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062
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),

#undef GEN_LD
#undef GEN_LDU
#undef GEN_LDUX
9063
#undef GEN_LDX_E
9064 9065 9066 9067 9068 9069 9070
#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),
9071 9072
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087
#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)
9088
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
9089 9090 9091 9092 9093 9094 9095
#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
9096
#undef GEN_STX_E
9097 9098 9099 9100 9101 9102 9103
#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),
9104 9105
#define GEN_STX_E(name, stop, opc2, opc3, type, type2)                        \
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117
#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)
9118
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
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
#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)
9144
GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
9145 9146
GEN_HANDLER_E(lfdp, 0x39, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205),
9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169

#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)
9170 9171
GEN_HANDLER_E(stfdp, 0x3D, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205),
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 9279 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 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 9386 9387 9388 9389 9390 9391

#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),
9392
GEN_VXFORM_NOA(vexptefp, 5, 6),
9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419 9420
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
9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498
#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),
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

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

9524
#include "helper_regs.h"
A
Andreas Färber 已提交
9525
#include "translate_init.c"
B
bellard 已提交
9526

9527
/*****************************************************************************/
9528
/* Misc PowerPC helpers */
9529 9530
void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                        int flags)
B
bellard 已提交
9531
{
9532 9533 9534
#define RGPL  4
#define RFPL  4

9535 9536
    PowerPCCPU *cpu = POWERPC_CPU(cs);
    CPUPPCState *env = &cpu->env;
B
bellard 已提交
9537 9538
    int i;

9539
    cpu_synchronize_state(cs);
9540

9541
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
9542
                TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
9543
                env->nip, env->lr, env->ctr, cpu_read_xer(env));
9544 9545 9546
    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);
9547
#if !defined(NO_TIMER_DUMP)
9548
    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
9549
#if !defined(CONFIG_USER_ONLY)
9550
                " DECR %08" PRIu32
9551 9552
#endif
                "\n",
J
j_mayer 已提交
9553
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
9554 9555 9556 9557
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
9558
#endif
9559
    for (i = 0; i < 32; i++) {
9560 9561
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
9562
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
9563
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
9564
            cpu_fprintf(f, "\n");
9565
    }
9566
    cpu_fprintf(f, "CR ");
9567
    for (i = 0; i < 8; i++)
B
bellard 已提交
9568 9569
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
9570 9571 9572 9573 9574 9575 9576 9577
    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 已提交
9578
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
9579
    }
9580 9581
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
9582 9583 9584
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
9585
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
9586
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
9587
            cpu_fprintf(f, "\n");
B
bellard 已提交
9588
    }
9589
    cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
9590
#if !defined(CONFIG_USER_ONLY)
S
Scott Wood 已提交
9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 9636 9637 9638
    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 已提交
9639 9640 9641 9642 9643 9644
#if defined(TARGET_PPC64)
    if (env->flags & POWERPC_FLAG_CFAR) {
        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
    }
#endif

S
Scott Wood 已提交
9645 9646 9647 9648 9649 9650 9651 9652 9653 9654
    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_64B:
#endif
        cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
        break;
A
Alexander Graf 已提交
9655
    case POWERPC_MMU_BOOKE206:
S
Scott Wood 已提交
9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 9672 9673
        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;
    }
9674
#endif
B
bellard 已提交
9675

9676 9677
#undef RGPL
#undef RFPL
B
bellard 已提交
9678 9679
}

9680 9681
void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
                             fprintf_function cpu_fprintf, int flags)
9682 9683
{
#if defined(DO_PPC_STATISTICS)
9684
    PowerPCCPU *cpu = POWERPC_CPU(cs);
A
Anthony Liguori 已提交
9685
    opc_handler_t **t1, **t2, **t3, *handler;
9686 9687
    int op1, op2, op3;

9688
    t1 = cpu->env.opcodes;
9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701
    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 已提交
9702
                                    "%016" PRIx64 " %" PRId64 "\n",
9703 9704 9705 9706 9707 9708 9709 9710
                                    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 已提交
9711
                                "%016" PRIx64 " %" PRId64 "\n",
9712 9713 9714 9715 9716 9717 9718
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
B
Blue Swirl 已提交
9719 9720
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
                        " %" PRId64 "\n",
9721 9722 9723 9724 9725 9726 9727
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

9728
/*****************************************************************************/
9729
static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
B
Blue Swirl 已提交
9730
                                                  TranslationBlock *tb,
9731
                                                  bool search_pc)
B
bellard 已提交
9732
{
9733
    CPUPPCState *env = &cpu->env;
9734
    DisasContext ctx, *ctxp = &ctx;
A
Anthony Liguori 已提交
9735
    opc_handler_t **table, *handler;
B
bellard 已提交
9736
    target_ulong pc_start;
B
bellard 已提交
9737
    uint16_t *gen_opc_end;
9738
    CPUBreakpoint *bp;
B
bellard 已提交
9739
    int j, lj = -1;
P
pbrook 已提交
9740 9741
    int num_insns;
    int max_insns;
B
bellard 已提交
9742 9743

    pc_start = tb->pc;
9744
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
9745
    ctx.nip = pc_start;
B
bellard 已提交
9746
    ctx.tb = tb;
9747
    ctx.exception = POWERPC_EXCP_NONE;
9748
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
9749
    ctx.mem_idx = env->mmu_idx;
9750 9751
    ctx.insns_flags = env->insns_flags;
    ctx.insns_flags2 = env->insns_flags2;
A
aurel32 已提交
9752 9753
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
9754
#if defined(TARGET_PPC64)
A
Alexander Graf 已提交
9755
    ctx.sf_mode = msr_is_64bit(env, env->msr);
D
David Gibson 已提交
9756
    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9757
#endif
B
bellard 已提交
9758
    ctx.fpu_enabled = msr_fp;
9759
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
9760 9761 9762
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
9763 9764 9765 9766
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
9767
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
9768
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
9769
    else
9770
        ctx.singlestep_enabled = 0;
9771
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
9772 9773 9774
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
9775
#if defined (DO_SINGLE_STEP) && 0
9776 9777 9778
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
9779 9780 9781 9782 9783
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

9784
    gen_tb_start();
9785
    /* Set env in case of segfault during code fetch */
9786 9787
    while (ctx.exception == POWERPC_EXCP_NONE
            && tcg_ctx.gen_opc_ptr < gen_opc_end) {
B
Blue Swirl 已提交
9788 9789
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9790
                if (bp->pc == ctx.nip) {
A
aurel32 已提交
9791
                    gen_debug_exception(ctxp);
9792 9793 9794 9795
                    break;
                }
            }
        }
9796
        if (unlikely(search_pc)) {
9797
            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
B
bellard 已提交
9798 9799 9800
            if (lj < j) {
                lj++;
                while (lj < j)
9801
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
9802
            }
9803
            tcg_ctx.gen_opc_pc[lj] = ctx.nip;
9804
            tcg_ctx.gen_opc_instr_start[lj] = 1;
9805
            tcg_ctx.gen_opc_icount[lj] = num_insns;
B
bellard 已提交
9806
        }
9807
        LOG_DISAS("----------------\n");
9808
        LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
9809
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
P
pbrook 已提交
9810 9811
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
A
aurel32 已提交
9812
        if (unlikely(ctx.le_mode)) {
9813
            ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
9814
        } else {
9815
            ctx.opcode = cpu_ldl_code(env, ctx.nip);
9816
        }
9817
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9818
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
9819
                    opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
9820
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
9821
            tcg_gen_debug_insn_start(ctx.nip);
9822
        }
B
bellard 已提交
9823
        ctx.nip += 4;
9824
        table = env->opcodes;
P
pbrook 已提交
9825
        num_insns++;
B
bellard 已提交
9826 9827 9828 9829 9830 9831 9832 9833 9834 9835
        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 ? */
9836
        if (unlikely(handler->handler == &gen_invalid)) {
9837 9838
            if (qemu_log_enabled()) {
                qemu_log("invalid/unsupported opcode: "
9839 9840 9841
                         "%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 已提交
9842
            }
9843
        } else {
9844 9845 9846 9847 9848 9849 9850 9851 9852
            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)) {
9853 9854
                if (qemu_log_enabled()) {
                    qemu_log("invalid bits: %08x for opcode: "
9855
                             "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
9856
                             ctx.opcode & inval, opc1(ctx.opcode),
9857 9858
                             opc2(ctx.opcode), opc3(ctx.opcode),
                             ctx.opcode, ctx.nip - 4);
9859
                }
A
aurel32 已提交
9860
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
B
bellard 已提交
9861
                break;
B
bellard 已提交
9862 9863
            }
        }
B
bellard 已提交
9864
        (*(handler->handler))(&ctx);
9865 9866 9867
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
9868
        /* Check trace mode exceptions */
9869 9870 9871 9872 9873
        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 已提交
9874
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
9875
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
9876
                            (env->singlestep_enabled) ||
9877
                            singlestep ||
P
pbrook 已提交
9878
                            num_insns >= max_insns)) {
9879 9880 9881
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
9882
            break;
9883
        }
9884
    }
P
pbrook 已提交
9885 9886
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
9887
    if (ctx.exception == POWERPC_EXCP_NONE) {
9888
        gen_goto_tb(&ctx, 0, ctx.nip);
9889
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
9890
        if (unlikely(env->singlestep_enabled)) {
A
aurel32 已提交
9891
            gen_debug_exception(ctxp);
9892
        }
9893
        /* Generate the return instruction */
B
bellard 已提交
9894
        tcg_gen_exit_tb(0);
9895
    }
9896
    gen_tb_end(tb, num_insns);
9897
    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
9898
    if (unlikely(search_pc)) {
9899
        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
9900 9901
        lj++;
        while (lj <= j)
9902
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
9903
    } else {
B
bellard 已提交
9904
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
9905
        tb->icount = num_insns;
9906
    }
9907
#if defined(DEBUG_DISAS)
9908
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9909
        int flags;
9910
        flags = env->bfd_mach;
A
aurel32 已提交
9911
        flags |= ctx.le_mode << 16;
9912
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
B
Blue Swirl 已提交
9913
        log_target_disas(env, pc_start, ctx.nip - pc_start, flags);
9914
        qemu_log("\n");
9915
    }
B
bellard 已提交
9916 9917 9918
#endif
}

9919
void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9920
{
9921
    gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, false);
B
bellard 已提交
9922 9923
}

9924
void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
B
bellard 已提交
9925
{
9926
    gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, true);
B
bellard 已提交
9927
}
A
aurel32 已提交
9928

9929
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
A
aurel32 已提交
9930
{
9931
    env->nip = tcg_ctx.gen_opc_pc[pc_pos];
A
aurel32 已提交
9932
}