translate.c 246.8 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

P
Peter Maydell 已提交
21
#include "qemu/osdep.h"
B
bellard 已提交
22
#include "cpu.h"
23
#include "internal.h"
24
#include "disas/disas.h"
25
#include "exec/exec-all.h"
B
bellard 已提交
26
#include "tcg-op.h"
27
#include "qemu/host-utils.h"
P
Paolo Bonzini 已提交
28
#include "exec/cpu_ldst.h"
B
bellard 已提交
29

30 31
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
P
pbrook 已提交
32

33
#include "trace-tcg.h"
34
#include "exec/translator.h"
35
#include "exec/log.h"
36 37


38 39 40 41
#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2
#define GDBSTUB_SINGLE_STEP 0x4

42
/* Include definitions for instructions classes and implementations flags */
43
//#define PPC_DEBUG_DISAS
44
//#define DO_PPC_STATISTICS
B
bellard 已提交
45

46
#ifdef PPC_DEBUG_DISAS
47
#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
48 49 50
#else
#  define LOG_DISAS(...) do { } while (0)
#endif
51 52
/*****************************************************************************/
/* Code translation helpers                                                  */
B
bellard 已提交
53

A
aurel32 已提交
54
/* global register indexes */
55 56
static char cpu_reg_names[10*3 + 22*4 /* GPR */
    + 10*4 + 22*5 /* SPE GPRh */
A
aurel32 已提交
57
    + 10*4 + 22*5 /* FPR */
A
aurel32 已提交
58
    + 2*(10*6 + 22*7) /* AVRh, AVRl */
T
Tom Musta 已提交
59
    + 10*5 + 22*6 /* VSR */
A
aurel32 已提交
60
    + 8*5 /* CRF */];
A
aurel32 已提交
61 62
static TCGv cpu_gpr[32];
static TCGv cpu_gprh[32];
P
pbrook 已提交
63 64
static TCGv_i64 cpu_fpr[32];
static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
T
Tom Musta 已提交
65
static TCGv_i64 cpu_vsr[32];
P
pbrook 已提交
66
static TCGv_i32 cpu_crf[8];
A
aurel32 已提交
67
static TCGv cpu_nip;
68
static TCGv cpu_msr;
A
aurel32 已提交
69 70
static TCGv cpu_ctr;
static TCGv cpu_lr;
D
David Gibson 已提交
71 72 73
#if defined(TARGET_PPC64)
static TCGv cpu_cfar;
#endif
74
static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca, cpu_ov32, cpu_ca32;
75
static TCGv cpu_reserve;
76
static TCGv cpu_reserve_val;
77
static TCGv cpu_fpscr;
A
aurel32 已提交
78
static TCGv_i32 cpu_access_type;
A
aurel32 已提交
79

80
#include "exec/gen-icount.h"
P
pbrook 已提交
81 82 83

void ppc_translate_init(void)
{
A
aurel32 已提交
84 85
    int i;
    char* p;
86
    size_t cpu_reg_names_size;
A
aurel32 已提交
87 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);
93
        cpu_crf[i] = tcg_global_mem_new_i32(cpu_env,
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);
101
        cpu_gpr[i] = tcg_global_mem_new(cpu_env,
102
                                        offsetof(CPUPPCState, gpr[i]), p);
A
aurel32 已提交
103
        p += (i < 10) ? 3 : 4;
104 105
        cpu_reg_names_size -= (i < 10) ? 3 : 4;
        snprintf(p, cpu_reg_names_size, "r%dH", i);
106
        cpu_gprh[i] = tcg_global_mem_new(cpu_env,
107
                                         offsetof(CPUPPCState, gprh[i]), p);
A
aurel32 已提交
108
        p += (i < 10) ? 4 : 5;
109
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
110

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

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

128
        snprintf(p, cpu_reg_names_size, "avr%dL", i);
129
#ifdef HOST_WORDS_BIGENDIAN
130
        cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env,
131
                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
132
#else
133
        cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env,
134
                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
135
#endif
136
        p += (i < 10) ? 6 : 7;
137
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
T
Tom Musta 已提交
138
        snprintf(p, cpu_reg_names_size, "vsr%d", i);
139 140
        cpu_vsr[i] = tcg_global_mem_new_i64(cpu_env,
                                            offsetof(CPUPPCState, vsr[i]), p);
T
Tom Musta 已提交
141 142
        p += (i < 10) ? 5 : 6;
        cpu_reg_names_size -= (i < 10) ? 5 : 6;
A
aurel32 已提交
143
    }
A
aurel32 已提交
144

145
    cpu_nip = tcg_global_mem_new(cpu_env,
146
                                 offsetof(CPUPPCState, nip), "nip");
A
aurel32 已提交
147

148
    cpu_msr = tcg_global_mem_new(cpu_env,
149
                                 offsetof(CPUPPCState, msr), "msr");
150

151
    cpu_ctr = tcg_global_mem_new(cpu_env,
152
                                 offsetof(CPUPPCState, ctr), "ctr");
A
aurel32 已提交
153

154
    cpu_lr = tcg_global_mem_new(cpu_env,
155
                                offsetof(CPUPPCState, lr), "lr");
A
aurel32 已提交
156

D
David Gibson 已提交
157
#if defined(TARGET_PPC64)
158
    cpu_cfar = tcg_global_mem_new(cpu_env,
159
                                  offsetof(CPUPPCState, cfar), "cfar");
D
David Gibson 已提交
160 161
#endif

162
    cpu_xer = tcg_global_mem_new(cpu_env,
163
                                 offsetof(CPUPPCState, xer), "xer");
164
    cpu_so = tcg_global_mem_new(cpu_env,
165
                                offsetof(CPUPPCState, so), "SO");
166
    cpu_ov = tcg_global_mem_new(cpu_env,
167
                                offsetof(CPUPPCState, ov), "OV");
168
    cpu_ca = tcg_global_mem_new(cpu_env,
169
                                offsetof(CPUPPCState, ca), "CA");
170 171 172 173
    cpu_ov32 = tcg_global_mem_new(cpu_env,
                                  offsetof(CPUPPCState, ov32), "OV32");
    cpu_ca32 = tcg_global_mem_new(cpu_env,
                                  offsetof(CPUPPCState, ca32), "CA32");
A
aurel32 已提交
174

175
    cpu_reserve = tcg_global_mem_new(cpu_env,
176
                                     offsetof(CPUPPCState, reserve_addr),
177
                                     "reserve_addr");
178 179 180
    cpu_reserve_val = tcg_global_mem_new(cpu_env,
                                     offsetof(CPUPPCState, reserve_val),
                                     "reserve_val");
181

182
    cpu_fpscr = tcg_global_mem_new(cpu_env,
183
                                   offsetof(CPUPPCState, fpscr), "fpscr");
184

185
    cpu_access_type = tcg_global_mem_new_i32(cpu_env,
186
                                             offsetof(CPUPPCState, access_type), "access_type");
P
pbrook 已提交
187 188
}

B
bellard 已提交
189
/* internal defines */
190
struct DisasContext {
191
    DisasContextBase base;
B
bellard 已提交
192
    uint32_t opcode;
193
    uint32_t exception;
B
bellard 已提交
194
    /* Routine used to access memory */
195
    bool pr, hv, dr, le_mode;
196
    bool lazy_tlb_flush;
197
    bool need_access_type;
B
bellard 已提交
198
    int mem_idx;
A
aurel32 已提交
199
    int access_type;
B
bellard 已提交
200
    /* Translation flags */
201
    TCGMemOp default_tcg_memop_mask;
202
#if defined(TARGET_PPC64)
203 204
    bool sf_mode;
    bool has_cfar;
205
#endif
206 207 208 209 210
    bool fpu_enabled;
    bool altivec_enabled;
    bool vsx_enabled;
    bool spe_enabled;
    bool tm_enabled;
211
    bool gtse;
A
Anthony Liguori 已提交
212
    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
213
    int singlestep_enabled;
214 215
    uint64_t insns_flags;
    uint64_t insns_flags2;
216
};
B
bellard 已提交
217

218 219 220 221 222 223 224 225 226 227
/* Return true iff byteswap is needed in a scalar memop */
static inline bool need_byteswap(const DisasContext *ctx)
{
#if defined(TARGET_WORDS_BIGENDIAN)
     return ctx->le_mode;
#else
     return !ctx->le_mode;
#endif
}

228 229 230 231 232 233 234
/* 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 已提交
235
struct opc_handler_t {
236 237 238 239
    /* invalid bits for instruction 1 (Rc(opcode) == 0) */
    uint32_t inval1;
    /* invalid bits for instruction 2 (Rc(opcode) == 1) */
    uint32_t inval2;
240
    /* instruction type */
241
    uint64_t type;
242 243
    /* extended instruction type */
    uint64_t type2;
B
bellard 已提交
244 245
    /* handler */
    void (*handler)(DisasContext *ctx);
246
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
247
    const char *oname;
248 249
#endif
#if defined(DO_PPC_STATISTICS)
250 251
    uint64_t count;
#endif
252
};
B
bellard 已提交
253

B
Blue Swirl 已提交
254
static inline void gen_set_access_type(DisasContext *ctx, int access_type)
A
aurel32 已提交
255
{
256
    if (ctx->need_access_type && ctx->access_type != access_type) {
A
aurel32 已提交
257 258 259
        tcg_gen_movi_i32(cpu_access_type, access_type);
        ctx->access_type = access_type;
    }
A
aurel32 已提交
260 261
}

B
Blue Swirl 已提交
262
static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
263
{
264 265 266 267
    if (NARROW_MODE(ctx)) {
        nip = (uint32_t)nip;
    }
    tcg_gen_movi_tl(cpu_nip, nip);
268 269
}

270
static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
A
aurel32 已提交
271 272
{
    TCGv_i32 t0, t1;
273 274 275 276

    /* These are all synchronous exceptions, we set the PC back to
     * the faulting instruction
     */
A
aurel32 已提交
277
    if (ctx->exception == POWERPC_EXCP_NONE) {
278
        gen_update_nip(ctx, ctx->base.pc_next - 4);
A
aurel32 已提交
279 280 281
    }
    t0 = tcg_const_i32(excp);
    t1 = tcg_const_i32(error);
282
    gen_helper_raise_exception_err(cpu_env, t0, t1);
A
aurel32 已提交
283 284 285 286
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
    ctx->exception = (excp);
}
287

288
static void gen_exception(DisasContext *ctx, uint32_t excp)
A
aurel32 已提交
289 290
{
    TCGv_i32 t0;
291 292 293 294

    /* These are all synchronous exceptions, we set the PC back to
     * the faulting instruction
     */
A
aurel32 已提交
295
    if (ctx->exception == POWERPC_EXCP_NONE) {
296
        gen_update_nip(ctx, ctx->base.pc_next - 4);
A
aurel32 已提交
297 298
    }
    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

304 305 306 307 308 309 310 311 312 313 314 315
static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
                              target_ulong nip)
{
    TCGv_i32 t0;

    gen_update_nip(ctx, nip);
    t0 = tcg_const_i32(excp);
    gen_helper_raise_exception(cpu_env, t0);
    tcg_temp_free_i32(t0);
    ctx->exception = (excp);
}

316
static void gen_debug_exception(DisasContext *ctx)
A
aurel32 已提交
317 318
{
    TCGv_i32 t0;
B
blueswir1 已提交
319

320 321 322
    /* These are all synchronous exceptions, we set the PC back to
     * the faulting instruction
     */
323 324
    if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
        (ctx->exception != POWERPC_EXCP_SYNC)) {
325
        gen_update_nip(ctx, ctx->base.pc_next);
326
    }
A
aurel32 已提交
327
    t0 = tcg_const_i32(EXCP_DEBUG);
328
    gen_helper_raise_exception(cpu_env, t0);
A
aurel32 已提交
329 330
    tcg_temp_free_i32(t0);
}
331

B
Blue Swirl 已提交
332
static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
A
aurel32 已提交
333
{
334 335 336 337 338 339 340 341 342 343 344 345 346
    /* Will be converted to program check if needed */
    gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_INVAL | error);
}

static inline void gen_priv_exception(DisasContext *ctx, uint32_t error)
{
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_PRIV | error);
}

static inline void gen_hvpriv_exception(DisasContext *ctx, uint32_t error)
{
    /* Will be converted to program check if needed */
    gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_PRIV | error);
A
aurel32 已提交
347
}
348

349
/* Stop translation */
B
Blue Swirl 已提交
350
static inline void gen_stop_exception(DisasContext *ctx)
351
{
352
    gen_update_nip(ctx, ctx->base.pc_next);
353
    ctx->exception = POWERPC_EXCP_STOP;
354 355
}

356
#ifndef CONFIG_USER_ONLY
357
/* No need to update nip here, as execution flow will change */
B
Blue Swirl 已提交
358
static inline void gen_sync_exception(DisasContext *ctx)
359
{
360
    ctx->exception = POWERPC_EXCP_SYNC;
361
}
362
#endif
363

B
bellard 已提交
364
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
365 366 367 368
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 已提交
369

370
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
371 372 373 374
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)
375

376 377 378
#define GEN_HANDLER_E_2(name, opc1, opc2, opc3, opc4, inval, type, type2)     \
GEN_OPCODE3(name, opc1, opc2, opc3, opc4, inval, type, type2)

379 380 381
#define GEN_HANDLER2_E_2(name, onam, opc1, opc2, opc3, opc4, inval, typ, typ2) \
GEN_OPCODE4(name, onam, opc1, opc2, opc3, opc4, inval, typ, typ2)

A
Anthony Liguori 已提交
382
typedef struct opcode_t {
383
    unsigned char opc1, opc2, opc3, opc4;
T
ths 已提交
384
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
385
    unsigned char pad[4];
386
#endif
A
Anthony Liguori 已提交
387
    opc_handler_t handler;
388
    const char *oname;
A
Anthony Liguori 已提交
389
} opcode_t;
B
bellard 已提交
390

391 392 393 394 395 396 397 398 399
/* Helpers for priv. check */
#define GEN_PRIV                                                \
    do {                                                        \
        gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; \
    } while (0)

#if defined(CONFIG_USER_ONLY)
#define CHK_HV GEN_PRIV
#define CHK_SV GEN_PRIV
400
#define CHK_HVRM GEN_PRIV
401 402 403 404 405 406 407 408 409 410 411 412 413
#else
#define CHK_HV                                                          \
    do {                                                                \
        if (unlikely(ctx->pr || !ctx->hv)) {                            \
            GEN_PRIV;                                                   \
        }                                                               \
    } while (0)
#define CHK_SV                   \
    do {                         \
        if (unlikely(ctx->pr)) { \
            GEN_PRIV;            \
        }                        \
    } while (0)
414 415 416 417 418 419
#define CHK_HVRM                                            \
    do {                                                    \
        if (unlikely(ctx->pr || !ctx->hv || ctx->dr)) {     \
            GEN_PRIV;                                       \
        }                                                   \
    } while (0)
420 421 422 423
#endif

#define CHK_NONE

424 425
/*****************************************************************************/
/* PowerPC instructions table                                                */
B
bellard 已提交
426

427
#if defined(DO_PPC_STATISTICS)
428
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
429
{                                                                             \
B
bellard 已提交
430 431 432
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
433
    .opc4 = 0xff,                                                             \
B
bellard 已提交
434
    .handler = {                                                              \
435 436 437 438 439 440 441 442 443 444 445 446 447
        .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,                                                              \
448
    .opc4 = 0xff,                                                             \
449 450 451
    .handler = {                                                              \
        .inval1  = invl1,                                                     \
        .inval2  = invl2,                                                     \
452
        .type = _typ,                                                         \
453
        .type2 = _typ2,                                                       \
B
bellard 已提交
454
        .handler = &gen_##name,                                               \
455
        .oname = stringify(name),                                             \
B
bellard 已提交
456
    },                                                                        \
457
    .oname = stringify(name),                                                 \
B
bellard 已提交
458
}
459
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
460
{                                                                             \
461 462 463
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
464
    .opc4 = 0xff,                                                             \
465
    .handler = {                                                              \
466
        .inval1  = invl,                                                      \
467
        .type = _typ,                                                         \
468
        .type2 = _typ2,                                                       \
469 470 471 472 473
        .handler = &gen_##name,                                               \
        .oname = onam,                                                        \
    },                                                                        \
    .oname = onam,                                                            \
}
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
#define GEN_OPCODE3(name, op1, op2, op3, op4, invl, _typ, _typ2)              \
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .opc4 = op4,                                                              \
    .handler = {                                                              \
        .inval1  = invl,                                                      \
        .type = _typ,                                                         \
        .type2 = _typ2,                                                       \
        .handler = &gen_##name,                                               \
        .oname = stringify(name),                                             \
    },                                                                        \
    .oname = stringify(name),                                                 \
}
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
#define GEN_OPCODE4(name, onam, op1, op2, op3, op4, invl, _typ, _typ2)        \
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .opc4 = op4,                                                              \
    .handler = {                                                              \
        .inval1  = invl,                                                      \
        .type = _typ,                                                         \
        .type2 = _typ2,                                                       \
        .handler = &gen_##name,                                               \
        .oname = onam,                                                        \
    },                                                                        \
    .oname = onam,                                                            \
}
504
#else
505
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
506
{                                                                             \
507 508 509
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
510
    .opc4 = 0xff,                                                             \
511
    .handler = {                                                              \
512 513 514 515 516 517 518 519 520 521 522 523
        .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,                                                              \
524
    .opc4 = 0xff,                                                             \
525 526 527
    .handler = {                                                              \
        .inval1  = invl1,                                                     \
        .inval2  = invl2,                                                     \
528
        .type = _typ,                                                         \
529
        .type2 = _typ2,                                                       \
530
        .handler = &gen_##name,                                               \
531 532 533
    },                                                                        \
    .oname = stringify(name),                                                 \
}
534
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
535 536 537 538
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
539
    .opc4 = 0xff,                                                             \
540
    .handler = {                                                              \
541
        .inval1  = invl,                                                      \
542
        .type = _typ,                                                         \
543
        .type2 = _typ2,                                                       \
544 545 546 547
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = onam,                                                            \
}
548 549 550 551 552 553 554 555 556 557 558 559 560 561
#define GEN_OPCODE3(name, op1, op2, op3, op4, invl, _typ, _typ2)              \
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .opc4 = op4,                                                              \
    .handler = {                                                              \
        .inval1  = invl,                                                      \
        .type = _typ,                                                         \
        .type2 = _typ2,                                                       \
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = stringify(name),                                                 \
}
562 563 564 565 566 567 568 569 570 571 572 573 574 575
#define GEN_OPCODE4(name, onam, op1, op2, op3, op4, invl, _typ, _typ2)        \
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .opc4 = op4,                                                              \
    .handler = {                                                              \
        .inval1  = invl,                                                      \
        .type = _typ,                                                         \
        .type2 = _typ2,                                                       \
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = onam,                                                            \
}
576
#endif
577

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

B
Blue Swirl 已提交
584
static inline void gen_store_spr(int reg, TCGv t)
585
{
586
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
587
}
588

589
/* Invalid instruction */
B
Blue Swirl 已提交
590
static void gen_invalid(DisasContext *ctx)
591
{
A
aurel32 已提交
592
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
593 594
}

A
Anthony Liguori 已提交
595
static opc_handler_t invalid_handler = {
596 597
    .inval1  = 0xFFFFFFFF,
    .inval2  = 0xFFFFFFFF,
598
    .type    = PPC_NONE,
599
    .type2   = PPC_NONE,
B
bellard 已提交
600 601 602
    .handler = gen_invalid,
};

603 604
/***                           Integer comparison                          ***/

B
Blue Swirl 已提交
605
static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
606
{
607
    TCGv t0 = tcg_temp_new();
608 609
    TCGv t1 = tcg_temp_new();
    TCGv_i32 t = tcg_temp_new_i32();
610

611 612 613 614 615
    tcg_gen_movi_tl(t0, CRF_EQ);
    tcg_gen_movi_tl(t1, CRF_LT);
    tcg_gen_movcond_tl((s ? TCG_COND_LT : TCG_COND_LTU), t0, arg0, arg1, t1, t0);
    tcg_gen_movi_tl(t1, CRF_GT);
    tcg_gen_movcond_tl((s ? TCG_COND_GT : TCG_COND_GTU), t0, arg0, arg1, t1, t0);
616

617 618 619
    tcg_gen_trunc_tl_i32(t, t0);
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
    tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t);
620 621

    tcg_temp_free(t0);
622 623
    tcg_temp_free(t1);
    tcg_temp_free_i32(t);
624 625
}

B
Blue Swirl 已提交
626
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
627
{
628
    TCGv t0 = tcg_const_tl(arg1);
629 630
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
631 632
}

B
Blue Swirl 已提交
633
static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
634
{
635
    TCGv t0, t1;
636 637
    t0 = tcg_temp_new();
    t1 = tcg_temp_new();
638
    if (s) {
639 640
        tcg_gen_ext32s_tl(t0, arg0);
        tcg_gen_ext32s_tl(t1, arg1);
641
    } else {
642 643
        tcg_gen_ext32u_tl(t0, arg0);
        tcg_gen_ext32u_tl(t1, arg1);
644
    }
645 646 647
    gen_op_cmp(t0, t1, s, crf);
    tcg_temp_free(t1);
    tcg_temp_free(t0);
648 649
}

B
Blue Swirl 已提交
650
static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
651
{
652
    TCGv t0 = tcg_const_tl(arg1);
653 654
    gen_op_cmp32(arg0, t0, s, crf);
    tcg_temp_free(t0);
655 656
}

B
Blue Swirl 已提交
657
static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
658
{
659
    if (NARROW_MODE(ctx)) {
660
        gen_op_cmpi32(reg, 0, 1, 0);
661
    } else {
662
        gen_op_cmpi(reg, 0, 1, 0);
663
    }
664 665 666
}

/* cmp */
B
Blue Swirl 已提交
667
static void gen_cmp(DisasContext *ctx)
668
{
669
    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
670 671
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   1, crfD(ctx->opcode));
672 673 674
    } else {
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     1, crfD(ctx->opcode));
675
    }
676 677 678
}

/* cmpi */
B
Blue Swirl 已提交
679
static void gen_cmpi(DisasContext *ctx)
680
{
681
    if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
682 683
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                    1, crfD(ctx->opcode));
684 685 686
    } else {
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                      1, crfD(ctx->opcode));
687
    }
688 689 690
}

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

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

714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
/* cmprb - range comparison: isupper, isaplha, islower*/
static void gen_cmprb(DisasContext *ctx)
{
    TCGv_i32 src1 = tcg_temp_new_i32();
    TCGv_i32 src2 = tcg_temp_new_i32();
    TCGv_i32 src2lo = tcg_temp_new_i32();
    TCGv_i32 src2hi = tcg_temp_new_i32();
    TCGv_i32 crf = cpu_crf[crfD(ctx->opcode)];

    tcg_gen_trunc_tl_i32(src1, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_trunc_tl_i32(src2, cpu_gpr[rB(ctx->opcode)]);

    tcg_gen_andi_i32(src1, src1, 0xFF);
    tcg_gen_ext8u_i32(src2lo, src2);
    tcg_gen_shri_i32(src2, src2, 8);
    tcg_gen_ext8u_i32(src2hi, src2);

    tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
    tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
    tcg_gen_and_i32(crf, src2lo, src2hi);

    if (ctx->opcode & 0x00200000) {
        tcg_gen_shri_i32(src2, src2, 8);
        tcg_gen_ext8u_i32(src2lo, src2);
        tcg_gen_shri_i32(src2, src2, 8);
        tcg_gen_ext8u_i32(src2hi, src2);
        tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
        tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
        tcg_gen_and_i32(src2lo, src2lo, src2hi);
        tcg_gen_or_i32(crf, crf, src2lo);
    }
745
    tcg_gen_shli_i32(crf, crf, CRF_GT_BIT);
746 747 748 749 750 751
    tcg_temp_free_i32(src1);
    tcg_temp_free_i32(src2);
    tcg_temp_free_i32(src2lo);
    tcg_temp_free_i32(src2hi);
}

752 753 754 755 756 757 758 759 760
#if defined(TARGET_PPC64)
/* cmpeqb */
static void gen_cmpeqb(DisasContext *ctx)
{
    gen_helper_cmpeqb(cpu_crf[crfD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                      cpu_gpr[rB(ctx->opcode)]);
}
#endif

761
/* isel (PowerPC 2.03 specification) */
B
Blue Swirl 已提交
762
static void gen_isel(DisasContext *ctx)
763 764
{
    uint32_t bi = rC(ctx->opcode);
765 766 767
    uint32_t mask = 0x08 >> (bi & 0x03);
    TCGv t0 = tcg_temp_new();
    TCGv zr;
768

769 770 771 772 773 774 775 776 777
    tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]);
    tcg_gen_andi_tl(t0, t0, mask);

    zr = tcg_const_tl(0);
    tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rD(ctx->opcode)], t0, zr,
                       rA(ctx->opcode) ? cpu_gpr[rA(ctx->opcode)] : zr,
                       cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(zr);
    tcg_temp_free(t0);
778 779
}

780 781 782 783 784 785 786
/* 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 已提交
787 788
/***                           Integer arithmetic                          ***/

B
Blue Swirl 已提交
789 790
static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
                                           TCGv arg1, TCGv arg2, int sub)
791
{
792
    TCGv t0 = tcg_temp_new();
B
bellard 已提交
793

794
    tcg_gen_xor_tl(cpu_ov, arg0, arg2);
795
    tcg_gen_xor_tl(t0, arg1, arg2);
796 797 798 799 800 801
    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);
802
    if (NARROW_MODE(ctx)) {
803 804 805 806 807 808 809 810
        tcg_gen_extract_tl(cpu_ov, cpu_ov, 31, 1);
        if (is_isa300(ctx)) {
            tcg_gen_mov_tl(cpu_ov32, cpu_ov);
        }
    } else {
        if (is_isa300(ctx)) {
            tcg_gen_extract_tl(cpu_ov32, cpu_ov, 31, 1);
        }
811
        tcg_gen_extract_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1, 1);
812 813
    }
    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
B
bellard 已提交
814 815
}

816 817 818 819 820 821 822 823 824 825 826
static inline void gen_op_arith_compute_ca32(DisasContext *ctx,
                                             TCGv res, TCGv arg0, TCGv arg1,
                                             int sub)
{
    TCGv t0;

    if (!is_isa300(ctx)) {
        return;
    }

    t0 = tcg_temp_new();
827 828 829 830 831
    if (sub) {
        tcg_gen_eqv_tl(t0, arg0, arg1);
    } else {
        tcg_gen_xor_tl(t0, arg0, arg1);
    }
832 833 834 835 836
    tcg_gen_xor_tl(t0, t0, res);
    tcg_gen_extract_tl(cpu_ca32, t0, 32, 1);
    tcg_temp_free(t0);
}

837
/* Common add function */
B
Blue Swirl 已提交
838
static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
839 840
                                    TCGv arg2, bool add_ca, bool compute_ca,
                                    bool compute_ov, bool compute_rc0)
841
{
842
    TCGv t0 = ret;
843

844
    if (compute_ca || compute_ov) {
845
        t0 = tcg_temp_new();
846
    }
B
bellard 已提交
847

848
    if (compute_ca) {
849
        if (NARROW_MODE(ctx)) {
850 851 852
            /* 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.  */
853
            TCGv t1 = tcg_temp_new();
854 855
            tcg_gen_xor_tl(t1, arg1, arg2);        /* add without carry */
            tcg_gen_add_tl(t0, arg1, arg2);
856 857 858
            if (add_ca) {
                tcg_gen_add_tl(t0, t0, cpu_ca);
            }
859 860
            tcg_gen_xor_tl(cpu_ca, t0, t1);        /* bits changed w/ carry */
            tcg_temp_free(t1);
861
            tcg_gen_extract_tl(cpu_ca, cpu_ca, 32, 1);
862 863 864
            if (is_isa300(ctx)) {
                tcg_gen_mov_tl(cpu_ca32, cpu_ca);
            }
865
        } else {
866 867 868 869 870 871 872
            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);
            }
873
            gen_op_arith_compute_ca32(ctx, t0, arg1, arg2, 0);
874
            tcg_temp_free(zero);
875 876 877 878 879 880
        }
    } else {
        tcg_gen_add_tl(t0, arg1, arg2);
        if (add_ca) {
            tcg_gen_add_tl(t0, t0, cpu_ca);
        }
881
    }
B
bellard 已提交
882

883 884 885
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
    }
886
    if (unlikely(compute_rc0)) {
887
        gen_set_Rc0(ctx, t0);
888
    }
889

R
Richard Henderson 已提交
890
    if (t0 != ret) {
891 892 893
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
894
}
895 896
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
897
static void glue(gen_, name)(DisasContext *ctx)                               \
898 899 900
{                                                                             \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
901
                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
902 903 904 905
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
                                add_ca, compute_ca, compute_ov)               \
906
static void glue(gen_, name)(DisasContext *ctx)                               \
907
{                                                                             \
908
    TCGv t0 = tcg_const_tl(const_val);                                        \
909 910
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
911
                     add_ca, compute_ca, compute_ov, Rc(ctx->opcode));        \
912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
    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 已提交
931
static void gen_addi(DisasContext *ctx)
932
{
933 934 935 936 937 938
    target_long simm = SIMM(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        /* li case */
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
    } else {
939 940
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
                        cpu_gpr[rA(ctx->opcode)], simm);
941
    }
942
}
943
/* addic  addic.*/
944
static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
945
{
946 947 948 949
    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);
950
}
B
Blue Swirl 已提交
951 952

static void gen_addic(DisasContext *ctx)
953
{
954
    gen_op_addic(ctx, 0);
955
}
B
Blue Swirl 已提交
956 957

static void gen_addic_(DisasContext *ctx)
958
{
959
    gen_op_addic(ctx, 1);
960
}
B
Blue Swirl 已提交
961

962
/* addis */
B
Blue Swirl 已提交
963
static void gen_addis(DisasContext *ctx)
964
{
965 966 967 968 969 970
    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 {
971 972
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
                        cpu_gpr[rA(ctx->opcode)], simm << 16);
973
    }
974
}
975

976 977 978 979 980
/* addpcis */
static void gen_addpcis(DisasContext *ctx)
{
    target_long d = DX(ctx->opcode);

981
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], ctx->base.pc_next + (d << 16));
982 983
}

B
Blue Swirl 已提交
984 985
static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign, int compute_ov)
986
{
987 988 989 990
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
    TCGv_i32 t2 = tcg_temp_new_i32();
    TCGv_i32 t3 = tcg_temp_new_i32();
991

992 993
    tcg_gen_trunc_tl_i32(t0, arg1);
    tcg_gen_trunc_tl_i32(t1, arg2);
994
    if (sign) {
995 996 997 998 999 1000 1001 1002 1003
        tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t0, INT_MIN);
        tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, -1);
        tcg_gen_and_i32(t2, t2, t3);
        tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, 0);
        tcg_gen_or_i32(t2, t2, t3);
        tcg_gen_movi_i32(t3, 0);
        tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1);
        tcg_gen_div_i32(t3, t0, t1);
        tcg_gen_extu_i32_tl(ret, t3);
1004
    } else {
1005 1006 1007 1008 1009
        tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t1, 0);
        tcg_gen_movi_i32(t3, 0);
        tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1);
        tcg_gen_divu_i32(t3, t0, t1);
        tcg_gen_extu_i32_tl(ret, t3);
1010 1011
    }
    if (compute_ov) {
1012
        tcg_gen_extu_i32_tl(cpu_ov, t2);
1013 1014 1015
        if (is_isa300(ctx)) {
            tcg_gen_extu_i32_tl(cpu_ov32, t2);
        }
1016
        tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1017
    }
P
pbrook 已提交
1018 1019
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
1020 1021 1022
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);

1023 1024
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
1025
}
1026 1027
/* Div functions */
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
B
Blue Swirl 已提交
1028
static void glue(gen_, name)(DisasContext *ctx)                                       \
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
{                                                                             \
    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);
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053

/* div[wd]eu[o][.] */
#define GEN_DIVE(name, hlpr, compute_ov)                                      \
static void gen_##name(DisasContext *ctx)                                     \
{                                                                             \
    TCGv_i32 t0 = tcg_const_i32(compute_ov);                                  \
    gen_helper_##hlpr(cpu_gpr[rD(ctx->opcode)], cpu_env,                      \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0); \
    tcg_temp_free_i32(t0);                                                    \
    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);                           \
    }                                                                         \
}

1054 1055
GEN_DIVE(divweu, divweu, 0);
GEN_DIVE(divweuo, divweu, 1);
1056 1057
GEN_DIVE(divwe, divwe, 0);
GEN_DIVE(divweo, divwe, 1);
1058

1059
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
1060 1061
static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign, int compute_ov)
1062
{
1063 1064 1065 1066
    TCGv_i64 t0 = tcg_temp_new_i64();
    TCGv_i64 t1 = tcg_temp_new_i64();
    TCGv_i64 t2 = tcg_temp_new_i64();
    TCGv_i64 t3 = tcg_temp_new_i64();
1067

1068 1069
    tcg_gen_mov_i64(t0, arg1);
    tcg_gen_mov_i64(t1, arg2);
1070
    if (sign) {
1071 1072 1073 1074 1075 1076 1077 1078
        tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t0, INT64_MIN);
        tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, -1);
        tcg_gen_and_i64(t2, t2, t3);
        tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, 0);
        tcg_gen_or_i64(t2, t2, t3);
        tcg_gen_movi_i64(t3, 0);
        tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1);
        tcg_gen_div_i64(ret, t0, t1);
1079
    } else {
1080 1081 1082 1083
        tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t1, 0);
        tcg_gen_movi_i64(t3, 0);
        tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1);
        tcg_gen_divu_i64(ret, t0, t1);
1084 1085
    }
    if (compute_ov) {
1086
        tcg_gen_mov_tl(cpu_ov, t2);
1087 1088 1089
        if (is_isa300(ctx)) {
            tcg_gen_mov_tl(cpu_ov32, t2);
        }
1090
        tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1091
    }
1092 1093 1094 1095 1096
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free_i64(t2);
    tcg_temp_free_i64(t3);

1097 1098
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
1099
}
1100

1101
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
B
Blue Swirl 已提交
1102
static void glue(gen_, name)(DisasContext *ctx)                                       \
1103
{                                                                             \
1104 1105 1106
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      sign, compute_ov);                                      \
1107
}
1108
/* divdu  divdu.  divduo  divduo.   */
1109 1110
GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1111
/* divd  divd.  divdo  divdo.   */
1112 1113
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1114 1115 1116

GEN_DIVE(divdeu, divdeu, 0);
GEN_DIVE(divdeuo, divdeu, 1);
1117 1118
GEN_DIVE(divde, divde, 0);
GEN_DIVE(divdeo, divde, 1);
1119
#endif
1120

1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
static inline void gen_op_arith_modw(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign)
{
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();

    tcg_gen_trunc_tl_i32(t0, arg1);
    tcg_gen_trunc_tl_i32(t1, arg2);
    if (sign) {
        TCGv_i32 t2 = tcg_temp_new_i32();
        TCGv_i32 t3 = tcg_temp_new_i32();
        tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t0, INT_MIN);
        tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, -1);
        tcg_gen_and_i32(t2, t2, t3);
        tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, 0);
        tcg_gen_or_i32(t2, t2, t3);
        tcg_gen_movi_i32(t3, 0);
        tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1);
        tcg_gen_rem_i32(t3, t0, t1);
        tcg_gen_ext_i32_tl(ret, t3);
        tcg_temp_free_i32(t2);
        tcg_temp_free_i32(t3);
    } else {
        TCGv_i32 t2 = tcg_const_i32(1);
        TCGv_i32 t3 = tcg_const_i32(0);
        tcg_gen_movcond_i32(TCG_COND_EQ, t1, t1, t3, t2, t1);
        tcg_gen_remu_i32(t3, t0, t1);
        tcg_gen_extu_i32_tl(ret, t3);
        tcg_temp_free_i32(t2);
        tcg_temp_free_i32(t3);
    }
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
}

#define GEN_INT_ARITH_MODW(name, opc3, sign)                                \
static void glue(gen_, name)(DisasContext *ctx)                             \
{                                                                           \
    gen_op_arith_modw(ctx, cpu_gpr[rD(ctx->opcode)],                        \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],   \
                      sign);                                                \
}

GEN_INT_ARITH_MODW(moduw, 0x08, 0);
GEN_INT_ARITH_MODW(modsw, 0x18, 1);

1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212
#if defined(TARGET_PPC64)
static inline void gen_op_arith_modd(DisasContext *ctx, TCGv ret, TCGv arg1,
                                     TCGv arg2, int sign)
{
    TCGv_i64 t0 = tcg_temp_new_i64();
    TCGv_i64 t1 = tcg_temp_new_i64();

    tcg_gen_mov_i64(t0, arg1);
    tcg_gen_mov_i64(t1, arg2);
    if (sign) {
        TCGv_i64 t2 = tcg_temp_new_i64();
        TCGv_i64 t3 = tcg_temp_new_i64();
        tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t0, INT64_MIN);
        tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, -1);
        tcg_gen_and_i64(t2, t2, t3);
        tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, 0);
        tcg_gen_or_i64(t2, t2, t3);
        tcg_gen_movi_i64(t3, 0);
        tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1);
        tcg_gen_rem_i64(ret, t0, t1);
        tcg_temp_free_i64(t2);
        tcg_temp_free_i64(t3);
    } else {
        TCGv_i64 t2 = tcg_const_i64(1);
        TCGv_i64 t3 = tcg_const_i64(0);
        tcg_gen_movcond_i64(TCG_COND_EQ, t1, t1, t3, t2, t1);
        tcg_gen_remu_i64(ret, t0, t1);
        tcg_temp_free_i64(t2);
        tcg_temp_free_i64(t3);
    }
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
}

#define GEN_INT_ARITH_MODD(name, opc3, sign)                            \
static void glue(gen_, name)(DisasContext *ctx)                           \
{                                                                         \
  gen_op_arith_modd(ctx, cpu_gpr[rD(ctx->opcode)],                        \
                    cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],   \
                    sign);                                                \
}

GEN_INT_ARITH_MODD(modud, 0x08, 0);
GEN_INT_ARITH_MODD(modsd, 0x18, 1);
#endif

1213
/* mulhw  mulhw. */
B
Blue Swirl 已提交
1214
static void gen_mulhw(DisasContext *ctx)
1215
{
1216 1217
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1218

1219 1220 1221 1222 1223 1224
    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);
1225 1226
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1227
}
B
Blue Swirl 已提交
1228

1229
/* mulhwu  mulhwu.  */
B
Blue Swirl 已提交
1230
static void gen_mulhwu(DisasContext *ctx)
1231
{
1232 1233
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1234

1235 1236 1237 1238 1239 1240
    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);
1241 1242
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1243
}
B
Blue Swirl 已提交
1244

1245
/* mullw  mullw. */
B
Blue Swirl 已提交
1246
static void gen_mullw(DisasContext *ctx)
1247
{
T
Tom Musta 已提交
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
#if defined(TARGET_PPC64)
    TCGv_i64 t0, t1;
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
T
Tom Musta 已提交
1258 1259
    tcg_gen_mul_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
T
Tom Musta 已提交
1260
#endif
1261 1262
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1263
}
B
Blue Swirl 已提交
1264

1265
/* mullwo  mullwo. */
B
Blue Swirl 已提交
1266
static void gen_mullwo(DisasContext *ctx)
1267
{
1268 1269
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t1 = tcg_temp_new_i32();
1270

1271 1272 1273
    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);
T
Tom Musta 已提交
1274
#if defined(TARGET_PPC64)
T
Tom Musta 已提交
1275 1276 1277
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], t0);
T
Tom Musta 已提交
1278
#endif
1279 1280 1281 1282

    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);
1283 1284 1285
    if (is_isa300(ctx)) {
        tcg_gen_mov_tl(cpu_ov32, cpu_ov);
    }
1286 1287 1288 1289
    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);

    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
1290 1291
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1292
}
B
Blue Swirl 已提交
1293

1294
/* mulli */
B
Blue Swirl 已提交
1295
static void gen_mulli(DisasContext *ctx)
1296
{
1297 1298
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                    SIMM(ctx->opcode));
1299
}
1300

1301
#if defined(TARGET_PPC64)
1302
/* mulhd  mulhd. */
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313
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)]);
    }
}

1314
/* mulhdu  mulhdu. */
1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
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 已提交
1325

1326
/* mulld  mulld. */
B
Blue Swirl 已提交
1327
static void gen_mulld(DisasContext *ctx)
1328
{
1329 1330 1331 1332
    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)]);
1333
}
1334

1335
/* mulldo  mulldo. */
1336 1337
static void gen_mulldo(DisasContext *ctx)
{
1338 1339 1340 1341 1342 1343 1344 1345 1346
    TCGv_i64 t0 = tcg_temp_new_i64();
    TCGv_i64 t1 = tcg_temp_new_i64();

    tcg_gen_muls2_i64(t0, t1, cpu_gpr[rA(ctx->opcode)],
                      cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], t0);

    tcg_gen_sari_i64(t0, t0, 63);
    tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1);
1347 1348 1349
    if (is_isa300(ctx)) {
        tcg_gen_mov_tl(cpu_ov32, cpu_ov);
    }
1350 1351 1352 1353 1354
    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);

    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);

1355 1356 1357 1358
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
    }
}
1359
#endif
1360 1361

/* Common subf function */
B
Blue Swirl 已提交
1362
static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
1363 1364
                                     TCGv arg2, bool add_ca, bool compute_ca,
                                     bool compute_ov, bool compute_rc0)
B
bellard 已提交
1365
{
1366
    TCGv t0 = ret;
B
bellard 已提交
1367

1368
    if (compute_ca || compute_ov) {
1369
        t0 = tcg_temp_new();
1370
    }
1371

1372 1373 1374
    if (compute_ca) {
        /* dest = ~arg1 + arg2 [+ ca].  */
        if (NARROW_MODE(ctx)) {
1375 1376 1377
            /* 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.  */
1378
            TCGv inv1 = tcg_temp_new();
1379
            TCGv t1 = tcg_temp_new();
1380 1381
            tcg_gen_not_tl(inv1, arg1);
            if (add_ca) {
1382
                tcg_gen_add_tl(t0, arg2, cpu_ca);
1383
            } else {
1384
                tcg_gen_addi_tl(t0, arg2, 1);
1385
            }
1386
            tcg_gen_xor_tl(t1, arg2, inv1);         /* add without carry */
1387
            tcg_gen_add_tl(t0, t0, inv1);
1388
            tcg_temp_free(inv1);
1389 1390
            tcg_gen_xor_tl(cpu_ca, t0, t1);         /* bits changes w/ carry */
            tcg_temp_free(t1);
1391
            tcg_gen_extract_tl(cpu_ca, cpu_ca, 32, 1);
1392 1393 1394
            if (is_isa300(ctx)) {
                tcg_gen_mov_tl(cpu_ca32, cpu_ca);
            }
1395
        } else if (add_ca) {
R
Richard Henderson 已提交
1396 1397
            TCGv zero, inv1 = tcg_temp_new();
            tcg_gen_not_tl(inv1, arg1);
1398 1399
            zero = tcg_const_tl(0);
            tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero);
R
Richard Henderson 已提交
1400
            tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero);
1401
            gen_op_arith_compute_ca32(ctx, t0, inv1, arg2, 0);
1402
            tcg_temp_free(zero);
R
Richard Henderson 已提交
1403
            tcg_temp_free(inv1);
1404
        } else {
1405
            tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
1406
            tcg_gen_sub_tl(t0, arg2, arg1);
1407
            gen_op_arith_compute_ca32(ctx, t0, arg1, arg2, 1);
1408
        }
1409 1410 1411 1412 1413 1414
    } 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 已提交
1415
    } else {
1416
        tcg_gen_sub_tl(t0, arg2, arg1);
1417
    }
1418

1419 1420 1421
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
    }
1422
    if (unlikely(compute_rc0)) {
1423
        gen_set_Rc0(ctx, t0);
1424
    }
1425

R
Richard Henderson 已提交
1426
    if (t0 != ret) {
1427 1428
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
B
bellard 已提交
1429 1430
    }
}
1431 1432
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
1433
static void glue(gen_, name)(DisasContext *ctx)                               \
1434 1435 1436
{                                                                             \
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1437
                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1438 1439 1440 1441
}
/* Sub functions with one operand and one immediate */
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
                                add_ca, compute_ca, compute_ov)               \
1442
static void glue(gen_, name)(DisasContext *ctx)                               \
1443
{                                                                             \
1444
    TCGv t0 = tcg_const_tl(const_val);                                        \
1445 1446
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], t0,                           \
1447
                      add_ca, compute_ca, compute_ov, Rc(ctx->opcode));       \
1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464
    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 已提交
1465

1466
/* subfic */
B
Blue Swirl 已提交
1467
static void gen_subfic(DisasContext *ctx)
B
bellard 已提交
1468
{
1469 1470 1471 1472
    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 已提交
1473 1474
}

1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485
/* 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)
{
1486 1487 1488 1489
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    if (unlikely(Rc(ctx->opcode))) {
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
    }
1490 1491 1492 1493 1494 1495 1496
}

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

B
bellard 已提交
1497
/***                            Integer logical                            ***/
1498
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1499
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1500
{                                                                             \
1501 1502
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
       cpu_gpr[rB(ctx->opcode)]);                                             \
1503
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1504
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1505 1506
}

1507
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
B
Blue Swirl 已提交
1508
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
1509
{                                                                             \
1510
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1511
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1512
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1513 1514 1515
}

/* and & and. */
1516
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
B
bellard 已提交
1517
/* andc & andc. */
1518
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
B
Blue Swirl 已提交
1519

1520
/* andi. */
B
Blue Swirl 已提交
1521
static void gen_andi_(DisasContext *ctx)
B
bellard 已提交
1522
{
1523 1524
    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 已提交
1525
}
B
Blue Swirl 已提交
1526

1527
/* andis. */
B
Blue Swirl 已提交
1528
static void gen_andis_(DisasContext *ctx)
B
bellard 已提交
1529
{
1530 1531
    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 已提交
1532
}
B
Blue Swirl 已提交
1533

1534
/* cntlzw */
B
Blue Swirl 已提交
1535
static void gen_cntlzw(DisasContext *ctx)
1536
{
1537 1538 1539 1540 1541 1542 1543
    TCGv_i32 t = tcg_temp_new_i32();

    tcg_gen_trunc_tl_i32(t, cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_clzi_i32(t, t, 32);
    tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t);
    tcg_temp_free_i32(t);

1544
    if (unlikely(Rc(ctx->opcode) != 0))
P
pbrook 已提交
1545
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1546
}
1547 1548 1549 1550

/* cnttzw */
static void gen_cnttzw(DisasContext *ctx)
{
1551 1552 1553 1554 1555 1556 1557
    TCGv_i32 t = tcg_temp_new_i32();

    tcg_gen_trunc_tl_i32(t, cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_ctzi_i32(t, t, 32);
    tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t);
    tcg_temp_free_i32(t);

1558 1559 1560 1561 1562
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
    }
}

B
bellard 已提交
1563
/* eqv & eqv. */
1564
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
B
bellard 已提交
1565
/* extsb & extsb. */
1566
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
B
bellard 已提交
1567
/* extsh & extsh. */
1568
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
B
bellard 已提交
1569
/* nand & nand. */
1570
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
B
bellard 已提交
1571
/* nor & nor. */
1572
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
B
Blue Swirl 已提交
1573

1574
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
1575 1576 1577 1578 1579 1580 1581 1582
static void gen_pause(DisasContext *ctx)
{
    TCGv_i32 t0 = tcg_const_i32(0);
    tcg_gen_st_i32(t0, cpu_env,
                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
    tcg_temp_free_i32(t0);

    /* Stop translation, this gives other CPUs a chance to run */
1583
    gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
1584 1585 1586
}
#endif /* defined(TARGET_PPC64) */

1587
/* or & or. */
B
Blue Swirl 已提交
1588
static void gen_or(DisasContext *ctx)
1589
{
1590 1591 1592 1593 1594 1595 1596
    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) {
1597 1598 1599 1600
        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]);
1601
        if (unlikely(Rc(ctx->opcode) != 0))
1602
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1603
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1604
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1605
#if defined(TARGET_PPC64)
1606
    } else if (rs != 0) { /* 0 is nop */
1607 1608
        int prio = 0;

1609 1610 1611
        switch (rs) {
        case 1:
            /* Set process priority to low */
1612
            prio = 2;
1613 1614 1615
            break;
        case 6:
            /* Set process priority to medium-low */
1616
            prio = 3;
1617 1618 1619
            break;
        case 2:
            /* Set process priority to normal */
1620
            prio = 4;
1621
            break;
1622 1623
#if !defined(CONFIG_USER_ONLY)
        case 31:
1624
            if (!ctx->pr) {
1625
                /* Set process priority to very low */
1626
                prio = 1;
1627 1628 1629
            }
            break;
        case 5:
1630
            if (!ctx->pr) {
1631
                /* Set process priority to medium-hight */
1632
                prio = 5;
1633 1634 1635
            }
            break;
        case 3:
1636
            if (!ctx->pr) {
1637
                /* Set process priority to high */
1638
                prio = 6;
1639 1640 1641
            }
            break;
        case 7:
1642
            if (ctx->hv && !ctx->pr) {
1643
                /* Set process priority to very high */
1644
                prio = 7;
1645 1646 1647
            }
            break;
#endif
1648 1649 1650
        default:
            break;
        }
1651
        if (prio) {
P
pbrook 已提交
1652
            TCGv t0 = tcg_temp_new();
1653
            gen_load_spr(t0, SPR_PPR);
1654 1655
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1656
            gen_store_spr(SPR_PPR, t0);
1657
            tcg_temp_free(t0);
1658
        }
1659
#if !defined(CONFIG_USER_ONLY)
1660 1661 1662 1663 1664 1665
        /* Pause out of TCG otherwise spin loops with smt_low eat too much
         * CPU and the kernel hangs.  This applies to all encodings other
         * than no-op, e.g., miso(rs=26), yield(27), mdoio(29), mdoom(30),
         * and all currently undefined.
         */
        gen_pause(ctx);
1666
#endif
1667
#endif
1668 1669
    }
}
B
bellard 已提交
1670
/* orc & orc. */
1671
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
B
Blue Swirl 已提交
1672

1673
/* xor & xor. */
B
Blue Swirl 已提交
1674
static void gen_xor(DisasContext *ctx)
1675 1676
{
    /* Optimisation for "set to zero" case */
1677
    if (rS(ctx->opcode) != rB(ctx->opcode))
A
aurel32 已提交
1678
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1679 1680
    else
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1681
    if (unlikely(Rc(ctx->opcode) != 0))
1682
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1683
}
B
Blue Swirl 已提交
1684

1685
/* ori */
B
Blue Swirl 已提交
1686
static void gen_ori(DisasContext *ctx)
B
bellard 已提交
1687
{
1688
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1689

1690 1691
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        return;
1692
    }
1693
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1694
}
B
Blue Swirl 已提交
1695

1696
/* oris */
B
Blue Swirl 已提交
1697
static void gen_oris(DisasContext *ctx)
B
bellard 已提交
1698
{
1699
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1700

1701 1702 1703
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1704
    }
1705
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1706
}
B
Blue Swirl 已提交
1707

1708
/* xori */
B
Blue Swirl 已提交
1709
static void gen_xori(DisasContext *ctx)
B
bellard 已提交
1710
{
1711
    target_ulong uimm = UIMM(ctx->opcode);
1712 1713 1714 1715 1716

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

1720
/* xoris */
B
Blue Swirl 已提交
1721
static void gen_xoris(DisasContext *ctx)
B
bellard 已提交
1722
{
1723
    target_ulong uimm = UIMM(ctx->opcode);
1724 1725 1726 1727 1728

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

1732
/* popcntb : PowerPC 2.03 specification */
B
Blue Swirl 已提交
1733
static void gen_popcntb(DisasContext *ctx)
1734
{
1735 1736 1737 1738 1739
    gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
}

static void gen_popcntw(DisasContext *ctx)
{
R
Richard Henderson 已提交
1740
#if defined(TARGET_PPC64)
1741
    gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
R
Richard Henderson 已提交
1742 1743 1744
#else
    tcg_gen_ctpop_i32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
#endif
1745 1746
}

1747
#if defined(TARGET_PPC64)
1748 1749 1750
/* popcntd: PowerPC 2.06 specification */
static void gen_popcntd(DisasContext *ctx)
{
R
Richard Henderson 已提交
1751
    tcg_gen_ctpop_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1752
}
1753
#endif
1754

1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786
/* 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

1787 1788 1789 1790 1791 1792 1793 1794 1795
#if defined(TARGET_PPC64)
/* bpermd */
static void gen_bpermd(DisasContext *ctx)
{
    gen_helper_bpermd(cpu_gpr[rA(ctx->opcode)],
                      cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
}
#endif

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

1800
/* cntlzd */
B
Blue Swirl 已提交
1801
static void gen_cntlzd(DisasContext *ctx)
1802
{
1803
    tcg_gen_clzi_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 64);
1804 1805 1806
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1807 1808 1809 1810

/* cnttzd */
static void gen_cnttzd(DisasContext *ctx)
{
1811
    tcg_gen_ctzi_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 64);
1812 1813 1814 1815
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
    }
}
1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830

/* darn */
static void gen_darn(DisasContext *ctx)
{
    int l = L(ctx->opcode);

    if (l == 0) {
        gen_helper_darn32(cpu_gpr[rD(ctx->opcode)]);
    } else if (l <= 2) {
        /* Return 64-bit random for both CRN and RRN */
        gen_helper_darn64(cpu_gpr[rD(ctx->opcode)]);
    } else {
        tcg_gen_movi_i64(cpu_gpr[rD(ctx->opcode)], -1);
    }
}
1831 1832
#endif

B
bellard 已提交
1833
/***                             Integer rotate                            ***/
B
Blue Swirl 已提交
1834

1835
/* rlwimi & rlwimi. */
B
Blue Swirl 已提交
1836
static void gen_rlwimi(DisasContext *ctx)
B
bellard 已提交
1837
{
1838 1839 1840 1841 1842 1843 1844 1845
    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
    uint32_t sh = SH(ctx->opcode);
    uint32_t mb = MB(ctx->opcode);
    uint32_t me = ME(ctx->opcode);

    if (sh == (31-me) && mb <= me) {
        tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
1846 1847
    } else {
        target_ulong mask;
P
pbrook 已提交
1848
        TCGv t1;
1849

1850
#if defined(TARGET_PPC64)
1851 1852
        mb += 32;
        me += 32;
1853
#endif
1854
        mask = MASK(mb, me);
1855

P
pbrook 已提交
1856
        t1 = tcg_temp_new();
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870
        if (mask <= 0xffffffffu) {
            TCGv_i32 t0 = tcg_temp_new_i32();
            tcg_gen_trunc_tl_i32(t0, t_rs);
            tcg_gen_rotli_i32(t0, t0, sh);
            tcg_gen_extu_i32_tl(t1, t0);
            tcg_temp_free_i32(t0);
        } else {
#if defined(TARGET_PPC64)
            tcg_gen_deposit_i64(t1, t_rs, t_rs, 32, 32);
            tcg_gen_rotli_i64(t1, t1, sh);
#else
            g_assert_not_reached();
#endif
        }
1871 1872 1873 1874

        tcg_gen_andi_tl(t1, t1, mask);
        tcg_gen_andi_tl(t_ra, t_ra, ~mask);
        tcg_gen_or_tl(t_ra, t_ra, t1);
1875 1876
        tcg_temp_free(t1);
    }
1877 1878 1879
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, t_ra);
    }
B
bellard 已提交
1880
}
B
Blue Swirl 已提交
1881

1882
/* rlwinm & rlwinm. */
B
Blue Swirl 已提交
1883
static void gen_rlwinm(DisasContext *ctx)
B
bellard 已提交
1884
{
1885 1886
    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1887 1888 1889 1890 1891 1892 1893 1894 1895 1896
    int sh = SH(ctx->opcode);
    int mb = MB(ctx->opcode);
    int me = ME(ctx->opcode);
    int len = me - mb + 1;
    int rsh = (32 - sh) & 31;

    if (sh != 0 && len > 0 && me == (31 - sh)) {
        tcg_gen_deposit_z_tl(t_ra, t_rs, sh, len);
    } else if (me == 31 && rsh + len <= 32) {
        tcg_gen_extract_tl(t_ra, t_rs, rsh, len);
1897
    } else {
1898
        target_ulong mask;
1899
#if defined(TARGET_PPC64)
1900 1901
        mb += 32;
        me += 32;
1902
#endif
1903
        mask = MASK(mb, me);
1904 1905 1906
        if (sh == 0) {
            tcg_gen_andi_tl(t_ra, t_rs, mask);
        } else if (mask <= 0xffffffffu) {
1907 1908 1909
            TCGv_i32 t0 = tcg_temp_new_i32();
            tcg_gen_trunc_tl_i32(t0, t_rs);
            tcg_gen_rotli_i32(t0, t0, sh);
1910
            tcg_gen_andi_i32(t0, t0, mask);
1911 1912
            tcg_gen_extu_i32_tl(t_ra, t0);
            tcg_temp_free_i32(t0);
1913 1914 1915 1916 1917 1918 1919 1920
        } else {
#if defined(TARGET_PPC64)
            tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
            tcg_gen_rotli_i64(t_ra, t_ra, sh);
            tcg_gen_andi_i64(t_ra, t_ra, mask);
#else
            g_assert_not_reached();
#endif
1921 1922 1923 1924
        }
    }
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, t_ra);
1925
    }
B
bellard 已提交
1926
}
B
Blue Swirl 已提交
1927

1928
/* rlwnm & rlwnm. */
B
Blue Swirl 已提交
1929
static void gen_rlwnm(DisasContext *ctx)
B
bellard 已提交
1930
{
1931 1932 1933 1934 1935
    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
    TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
    uint32_t mb = MB(ctx->opcode);
    uint32_t me = ME(ctx->opcode);
1936
    target_ulong mask;
1937

1938
#if defined(TARGET_PPC64)
1939 1940
    mb += 32;
    me += 32;
1941
#endif
1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964
    mask = MASK(mb, me);

    if (mask <= 0xffffffffu) {
        TCGv_i32 t0 = tcg_temp_new_i32();
        TCGv_i32 t1 = tcg_temp_new_i32();
        tcg_gen_trunc_tl_i32(t0, t_rb);
        tcg_gen_trunc_tl_i32(t1, t_rs);
        tcg_gen_andi_i32(t0, t0, 0x1f);
        tcg_gen_rotl_i32(t1, t1, t0);
        tcg_gen_extu_i32_tl(t_ra, t1);
        tcg_temp_free_i32(t0);
        tcg_temp_free_i32(t1);
    } else {
#if defined(TARGET_PPC64)
        TCGv_i64 t0 = tcg_temp_new_i64();
        tcg_gen_andi_i64(t0, t_rb, 0x1f);
        tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
        tcg_gen_rotl_i64(t_ra, t_ra, t0);
        tcg_temp_free_i64(t0);
#else
        g_assert_not_reached();
#endif
    }
1965

1966
    tcg_gen_andi_tl(t_ra, t_ra, mask);
1967 1968 1969

    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, t_ra);
B
bellard 已提交
1970 1971 1972
    }
}

1973 1974
#if defined(TARGET_PPC64)
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1975
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1976 1977 1978
{                                                                             \
    gen_##name(ctx, 0);                                                       \
}                                                                             \
B
Blue Swirl 已提交
1979 1980
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1981 1982 1983 1984
{                                                                             \
    gen_##name(ctx, 1);                                                       \
}
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
B
Blue Swirl 已提交
1985
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1986 1987 1988
{                                                                             \
    gen_##name(ctx, 0, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1989 1990
                                                                              \
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1991 1992 1993
{                                                                             \
    gen_##name(ctx, 0, 1);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1994 1995
                                                                              \
static void glue(gen_, name##2)(DisasContext *ctx)                            \
1996 1997 1998
{                                                                             \
    gen_##name(ctx, 1, 0);                                                    \
}                                                                             \
B
Blue Swirl 已提交
1999 2000
                                                                              \
static void glue(gen_, name##3)(DisasContext *ctx)                            \
2001 2002 2003
{                                                                             \
    gen_##name(ctx, 1, 1);                                                    \
}
J
j_mayer 已提交
2004

2005
static void gen_rldinm(DisasContext *ctx, int mb, int me, int sh)
J
j_mayer 已提交
2006
{
2007 2008
    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2009 2010
    int len = me - mb + 1;
    int rsh = (64 - sh) & 63;
2011

2012 2013 2014 2015
    if (sh != 0 && len > 0 && me == (63 - sh)) {
        tcg_gen_deposit_z_tl(t_ra, t_rs, sh, len);
    } else if (me == 63 && rsh + len <= 64) {
        tcg_gen_extract_tl(t_ra, t_rs, rsh, len);
2016
    } else {
2017 2018 2019 2020 2021
        tcg_gen_rotli_tl(t_ra, t_rs, sh);
        tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
    }
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, t_ra);
J
j_mayer 已提交
2022 2023
    }
}
2024

2025
/* rldicl - rldicl. */
B
Blue Swirl 已提交
2026
static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
2027
{
J
j_mayer 已提交
2028
    uint32_t sh, mb;
2029

J
j_mayer 已提交
2030 2031
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
2032
    gen_rldinm(ctx, mb, 63, sh);
2033
}
J
j_mayer 已提交
2034
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
2035

2036
/* rldicr - rldicr. */
B
Blue Swirl 已提交
2037
static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
2038
{
J
j_mayer 已提交
2039
    uint32_t sh, me;
2040

J
j_mayer 已提交
2041 2042
    sh = SH(ctx->opcode) | (shn << 5);
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
2043
    gen_rldinm(ctx, 0, me, sh);
2044
}
J
j_mayer 已提交
2045
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
2046

2047
/* rldic - rldic. */
B
Blue Swirl 已提交
2048
static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
2049
{
J
j_mayer 已提交
2050
    uint32_t sh, mb;
2051

J
j_mayer 已提交
2052 2053
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
2054 2055 2056 2057
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

2058
static void gen_rldnm(DisasContext *ctx, int mb, int me)
J
j_mayer 已提交
2059
{
2060 2061 2062
    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
    TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
2063
    TCGv t0;
2064

P
pbrook 已提交
2065
    t0 = tcg_temp_new();
2066 2067
    tcg_gen_andi_tl(t0, t_rb, 0x3f);
    tcg_gen_rotl_tl(t_ra, t_rs, t0);
2068
    tcg_temp_free(t0);
2069 2070 2071 2072 2073

    tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, t_ra);
    }
2074
}
J
j_mayer 已提交
2075

2076
/* rldcl - rldcl. */
B
Blue Swirl 已提交
2077
static inline void gen_rldcl(DisasContext *ctx, int mbn)
2078
{
J
j_mayer 已提交
2079
    uint32_t mb;
2080

J
j_mayer 已提交
2081
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
2082
    gen_rldnm(ctx, mb, 63);
2083
}
2084
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
2085

2086
/* rldcr - rldcr. */
B
Blue Swirl 已提交
2087
static inline void gen_rldcr(DisasContext *ctx, int men)
2088
{
J
j_mayer 已提交
2089
    uint32_t me;
2090

J
j_mayer 已提交
2091
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
2092
    gen_rldnm(ctx, 0, me);
2093
}
2094
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
2095

2096
/* rldimi - rldimi. */
2097
static void gen_rldimi(DisasContext *ctx, int mbn, int shn)
2098
{
2099 2100 2101 2102 2103
    TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
    TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
    uint32_t sh = SH(ctx->opcode) | (shn << 5);
    uint32_t mb = MB(ctx->opcode) | (mbn << 5);
    uint32_t me = 63 - sh;
2104

2105 2106
    if (mb <= me) {
        tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
2107
    } else {
2108 2109
        target_ulong mask = MASK(mb, me);
        TCGv t1 = tcg_temp_new();
2110

2111 2112 2113 2114
        tcg_gen_rotli_tl(t1, t_rs, sh);
        tcg_gen_andi_tl(t1, t1, mask);
        tcg_gen_andi_tl(t_ra, t_ra, ~mask);
        tcg_gen_or_tl(t_ra, t_ra, t1);
2115
        tcg_temp_free(t1);
J
j_mayer 已提交
2116
    }
2117 2118 2119
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, t_ra);
    }
2120
}
2121
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
2122 2123
#endif

B
bellard 已提交
2124
/***                             Integer shift                             ***/
B
Blue Swirl 已提交
2125

2126
/* slw & slw. */
B
Blue Swirl 已提交
2127
static void gen_slw(DisasContext *ctx)
2128
{
2129
    TCGv t0, t1;
2130

2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144
    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);
2145
    tcg_temp_free(t0);
2146
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
2147 2148 2149
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
2150

2151
/* sraw & sraw. */
B
Blue Swirl 已提交
2152
static void gen_sraw(DisasContext *ctx)
2153
{
2154
    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
P
pbrook 已提交
2155
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2156 2157 2158
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
2159

2160
/* srawi & srawi. */
B
Blue Swirl 已提交
2161
static void gen_srawi(DisasContext *ctx)
B
bellard 已提交
2162
{
2163
    int sh = SH(ctx->opcode);
2164 2165 2166
    TCGv dst = cpu_gpr[rA(ctx->opcode)];
    TCGv src = cpu_gpr[rS(ctx->opcode)];
    if (sh == 0) {
T
Tom Musta 已提交
2167
        tcg_gen_ext32s_tl(dst, src);
2168
        tcg_gen_movi_tl(cpu_ca, 0);
2169 2170 2171
        if (is_isa300(ctx)) {
            tcg_gen_movi_tl(cpu_ca32, 0);
        }
2172
    } else {
2173 2174 2175 2176 2177 2178 2179 2180
        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);
2181 2182 2183
        if (is_isa300(ctx)) {
            tcg_gen_mov_tl(cpu_ca32, cpu_ca);
        }
2184 2185 2186 2187
        tcg_gen_sari_tl(dst, dst, sh);
    }
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, dst);
2188
    }
B
bellard 已提交
2189
}
B
Blue Swirl 已提交
2190

2191
/* srw & srw. */
B
Blue Swirl 已提交
2192
static void gen_srw(DisasContext *ctx)
2193
{
2194
    TCGv t0, t1;
2195

2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206
    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 已提交
2207
    t1 = tcg_temp_new();
2208 2209
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2210 2211
    tcg_temp_free(t1);
    tcg_temp_free(t0);
2212 2213 2214
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2215

2216 2217
#if defined(TARGET_PPC64)
/* sld & sld. */
B
Blue Swirl 已提交
2218
static void gen_sld(DisasContext *ctx)
2219
{
2220
    TCGv t0, t1;
2221

2222 2223 2224 2225 2226 2227 2228 2229 2230
    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);
2231
    tcg_temp_free(t0);
2232 2233 2234
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
Blue Swirl 已提交
2235

2236
/* srad & srad. */
B
Blue Swirl 已提交
2237
static void gen_srad(DisasContext *ctx)
2238
{
2239
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
P
pbrook 已提交
2240
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2241 2242 2243
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2244
/* sradi & sradi. */
B
Blue Swirl 已提交
2245
static inline void gen_sradi(DisasContext *ctx, int n)
2246
{
2247
    int sh = SH(ctx->opcode) + (n << 5);
2248 2249 2250 2251
    TCGv dst = cpu_gpr[rA(ctx->opcode)];
    TCGv src = cpu_gpr[rS(ctx->opcode)];
    if (sh == 0) {
        tcg_gen_mov_tl(dst, src);
2252
        tcg_gen_movi_tl(cpu_ca, 0);
2253 2254 2255
        if (is_isa300(ctx)) {
            tcg_gen_movi_tl(cpu_ca32, 0);
        }
2256
    } else {
2257 2258 2259 2260 2261 2262 2263
        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);
2264 2265 2266
        if (is_isa300(ctx)) {
            tcg_gen_mov_tl(cpu_ca32, cpu_ca);
        }
2267 2268 2269 2270
        tcg_gen_sari_tl(dst, src, sh);
    }
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, dst);
2271 2272
    }
}
B
Blue Swirl 已提交
2273 2274

static void gen_sradi0(DisasContext *ctx)
2275 2276 2277
{
    gen_sradi(ctx, 0);
}
B
Blue Swirl 已提交
2278 2279

static void gen_sradi1(DisasContext *ctx)
2280 2281 2282
{
    gen_sradi(ctx, 1);
}
B
Blue Swirl 已提交
2283

2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307
/* extswsli & extswsli. */
static inline void gen_extswsli(DisasContext *ctx, int n)
{
    int sh = SH(ctx->opcode) + (n << 5);
    TCGv dst = cpu_gpr[rA(ctx->opcode)];
    TCGv src = cpu_gpr[rS(ctx->opcode)];

    tcg_gen_ext32s_tl(dst, src);
    tcg_gen_shli_tl(dst, dst, sh);
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_set_Rc0(ctx, dst);
    }
}

static void gen_extswsli0(DisasContext *ctx)
{
    gen_extswsli(ctx, 0);
}

static void gen_extswsli1(DisasContext *ctx)
{
    gen_extswsli(ctx, 1);
}

2308
/* srd & srd. */
B
Blue Swirl 已提交
2309
static void gen_srd(DisasContext *ctx)
2310
{
2311
    TCGv t0, t1;
2312

2313 2314 2315 2316 2317 2318 2319 2320 2321
    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);
2322
    tcg_temp_free(t0);
2323 2324 2325
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2326
#endif
B
bellard 已提交
2327

2328 2329
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
B
Blue Swirl 已提交
2330 2331
static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
                                      target_long maskl)
2332 2333 2334
{
    target_long simm = SIMM(ctx->opcode);

2335
    simm &= ~maskl;
A
aurel32 已提交
2336
    if (rA(ctx->opcode) == 0) {
2337 2338 2339
        if (NARROW_MODE(ctx)) {
            simm = (uint32_t)simm;
        }
2340
        tcg_gen_movi_tl(EA, simm);
A
aurel32 已提交
2341
    } else if (likely(simm != 0)) {
2342
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2343
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2344 2345 2346
            tcg_gen_ext32u_tl(EA, EA);
        }
    } else {
2347
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2348
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2349 2350 2351
        } else {
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
        }
A
aurel32 已提交
2352
    }
2353 2354
}

B
Blue Swirl 已提交
2355
static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2356
{
A
aurel32 已提交
2357
    if (rA(ctx->opcode) == 0) {
2358
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2359
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2360 2361 2362
        } else {
            tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
        }
A
aurel32 已提交
2363
    } else {
2364
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2365
        if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2366 2367 2368
            tcg_gen_ext32u_tl(EA, EA);
        }
    }
2369 2370
}

B
Blue Swirl 已提交
2371
static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2372
{
A
aurel32 已提交
2373
    if (rA(ctx->opcode) == 0) {
2374
        tcg_gen_movi_tl(EA, 0);
2375 2376
    } else if (NARROW_MODE(ctx)) {
        tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2377
    } else {
2378
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2379 2380 2381
    }
}

B
Blue Swirl 已提交
2382 2383
static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                target_long val)
A
aurel32 已提交
2384 2385
{
    tcg_gen_addi_tl(ret, arg1, val);
2386
    if (NARROW_MODE(ctx)) {
A
aurel32 已提交
2387 2388
        tcg_gen_ext32u_tl(ret, ret);
    }
2389 2390
}

2391 2392 2393 2394 2395 2396
static inline void gen_align_no_le(DisasContext *ctx)
{
    gen_exception_err(ctx, POWERPC_EXCP_ALIGN,
                      (ctx->opcode & 0x03FF0000) | POWERPC_EXCP_ALIGN_LE);
}

2397
/***                             Integer load                              ***/
2398
#define DEF_MEMOP(op) ((op) | ctx->default_tcg_memop_mask)
2399
#define BSWAP_MEMOP(op) ((op) | (ctx->default_tcg_memop_mask ^ MO_BSWAP))
A
aurel32 已提交
2400

2401 2402 2403 2404 2405 2406
#define GEN_QEMU_LOAD_TL(ldop, op)                                      \
static void glue(gen_qemu_, ldop)(DisasContext *ctx,                    \
                                  TCGv val,                             \
                                  TCGv addr)                            \
{                                                                       \
    tcg_gen_qemu_ld_tl(val, addr, ctx->mem_idx, op);                    \
A
aurel32 已提交
2407 2408
}

2409 2410 2411 2412 2413
GEN_QEMU_LOAD_TL(ld8u,  DEF_MEMOP(MO_UB))
GEN_QEMU_LOAD_TL(ld16u, DEF_MEMOP(MO_UW))
GEN_QEMU_LOAD_TL(ld16s, DEF_MEMOP(MO_SW))
GEN_QEMU_LOAD_TL(ld32u, DEF_MEMOP(MO_UL))
GEN_QEMU_LOAD_TL(ld32s, DEF_MEMOP(MO_SL))
2414

2415 2416 2417
GEN_QEMU_LOAD_TL(ld16ur, BSWAP_MEMOP(MO_UW))
GEN_QEMU_LOAD_TL(ld32ur, BSWAP_MEMOP(MO_UL))

2418 2419 2420 2421 2422 2423
#define GEN_QEMU_LOAD_64(ldop, op)                                  \
static void glue(gen_qemu_, glue(ldop, _i64))(DisasContext *ctx,    \
                                             TCGv_i64 val,          \
                                             TCGv addr)             \
{                                                                   \
    tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, op);               \
A
aurel32 已提交
2424 2425
}

2426 2427
GEN_QEMU_LOAD_64(ld8u,  DEF_MEMOP(MO_UB))
GEN_QEMU_LOAD_64(ld16u, DEF_MEMOP(MO_UW))
2428 2429
GEN_QEMU_LOAD_64(ld32u, DEF_MEMOP(MO_UL))
GEN_QEMU_LOAD_64(ld32s, DEF_MEMOP(MO_SL))
2430
GEN_QEMU_LOAD_64(ld64,  DEF_MEMOP(MO_Q))
A
aurel32 已提交
2431

2432 2433 2434 2435
#if defined(TARGET_PPC64)
GEN_QEMU_LOAD_64(ld64ur, BSWAP_MEMOP(MO_Q))
#endif

2436 2437 2438 2439 2440 2441
#define GEN_QEMU_STORE_TL(stop, op)                                     \
static void glue(gen_qemu_, stop)(DisasContext *ctx,                    \
                                  TCGv val,                             \
                                  TCGv addr)                            \
{                                                                       \
    tcg_gen_qemu_st_tl(val, addr, ctx->mem_idx, op);                    \
A
aurel32 已提交
2442 2443
}

2444 2445 2446
GEN_QEMU_STORE_TL(st8,  DEF_MEMOP(MO_UB))
GEN_QEMU_STORE_TL(st16, DEF_MEMOP(MO_UW))
GEN_QEMU_STORE_TL(st32, DEF_MEMOP(MO_UL))
A
aurel32 已提交
2447

2448 2449 2450
GEN_QEMU_STORE_TL(st16r, BSWAP_MEMOP(MO_UW))
GEN_QEMU_STORE_TL(st32r, BSWAP_MEMOP(MO_UL))

2451 2452 2453 2454 2455 2456
#define GEN_QEMU_STORE_64(stop, op)                               \
static void glue(gen_qemu_, glue(stop, _i64))(DisasContext *ctx,  \
                                              TCGv_i64 val,       \
                                              TCGv addr)          \
{                                                                 \
    tcg_gen_qemu_st_i64(val, addr, ctx->mem_idx, op);             \
A
aurel32 已提交
2457 2458
}

2459 2460
GEN_QEMU_STORE_64(st8,  DEF_MEMOP(MO_UB))
GEN_QEMU_STORE_64(st16, DEF_MEMOP(MO_UW))
2461
GEN_QEMU_STORE_64(st32, DEF_MEMOP(MO_UL))
2462
GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_Q))
A
aurel32 已提交
2463

2464 2465 2466 2467
#if defined(TARGET_PPC64)
GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_Q))
#endif

2468
#define GEN_LD(name, ldop, opc, type)                                         \
B
Blue Swirl 已提交
2469
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2470
{                                                                             \
A
aurel32 已提交
2471 2472 2473 2474 2475
    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 已提交
2476
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2477 2478
}

2479
#define GEN_LDU(name, ldop, opc, type)                                        \
B
Blue Swirl 已提交
2480
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2481
{                                                                             \
A
aurel32 已提交
2482
    TCGv EA;                                                                  \
2483 2484
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2485
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2486
        return;                                                               \
2487
    }                                                                         \
A
aurel32 已提交
2488
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2489
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2490
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2491
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2492
    else                                                                      \
A
aurel32 已提交
2493 2494
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2495 2496
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2497 2498
}

2499
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2500
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2501
{                                                                             \
A
aurel32 已提交
2502
    TCGv EA;                                                                  \
2503 2504
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2505
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2506
        return;                                                               \
2507
    }                                                                         \
A
aurel32 已提交
2508
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2509
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2510 2511
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2512 2513
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2514 2515
}

2516
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk)                   \
B
Blue Swirl 已提交
2517
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2518
{                                                                             \
A
aurel32 已提交
2519
    TCGv EA;                                                                  \
2520
    chk;                                                                      \
A
aurel32 已提交
2521 2522 2523 2524
    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 已提交
2525
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2526
}
2527

2528
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
2529 2530 2531 2532
    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_NONE)

#define GEN_LDX_HVRM(name, ldop, opc2, opc3, type)                            \
    GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_HVRM)
B
bellard 已提交
2533

2534 2535 2536 2537 2538
#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 已提交
2539 2540

/* lbz lbzu lbzux lbzx */
2541
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2542
/* lha lhau lhaux lhax */
2543
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2544
/* lhz lhzu lhzux lhzx */
2545
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2546
/* lwz lwzu lwzux lwzx */
2547
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2548 2549
#if defined(TARGET_PPC64)
/* lwaux */
2550
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2551
/* lwax */
2552
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2553
/* ldux */
2554
GEN_LDUX(ld, ld64_i64, 0x15, 0x01, PPC_64B);
2555
/* ldx */
2556
GEN_LDX(ld, ld64_i64, 0x15, 0x00, PPC_64B);
B
Blue Swirl 已提交
2557

2558
/* CI load/store variants */
2559
GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST)
2560 2561 2562 2563
GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x15, PPC_CILDST)
GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)

B
Blue Swirl 已提交
2564
static void gen_ld(DisasContext *ctx)
2565
{
A
aurel32 已提交
2566
    TCGv EA;
2567 2568 2569
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
A
aurel32 已提交
2570
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2571 2572 2573
            return;
        }
    }
A
aurel32 已提交
2574
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2575
    EA = tcg_temp_new();
A
aurel32 已提交
2576
    gen_addr_imm_index(ctx, EA, 0x03);
2577 2578
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2579
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2580 2581
    } else {
        /* ld - ldu */
2582
        gen_qemu_ld64_i64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2583 2584
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2585 2586
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2587
}
B
Blue Swirl 已提交
2588

2589
/* lq */
B
Blue Swirl 已提交
2590
static void gen_lq(DisasContext *ctx)
2591 2592
{
    int ra, rd;
2593
    TCGv EA, hi, lo;
2594

T
Tom Musta 已提交
2595 2596 2597 2598
    /* lq is a legal user mode instruction starting in ISA 2.07 */
    bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
    bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;

2599
    if (!legal_in_user_mode && ctx->pr) {
2600
        gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2601 2602
        return;
    }
T
Tom Musta 已提交
2603 2604

    if (!le_is_supported && ctx->le_mode) {
2605
        gen_align_no_le(ctx);
T
Tom Musta 已提交
2606 2607
        return;
    }
2608 2609 2610
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
A
aurel32 已提交
2611
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2612 2613
        return;
    }
T
Tom Musta 已提交
2614

A
aurel32 已提交
2615
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2616
    EA = tcg_temp_new();
A
aurel32 已提交
2617
    gen_addr_imm_index(ctx, EA, 0x0F);
T
Tom Musta 已提交
2618

2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641
    /* Note that the low part is always in RD+1, even in LE mode.  */
    lo = cpu_gpr[rd + 1];
    hi = cpu_gpr[rd];

    if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
#ifdef CONFIG_ATOMIC128
        TCGv_i32 oi = tcg_temp_new_i32();
        if (ctx->le_mode) {
            tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
            gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
        } else {
            tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
            gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
        }
        tcg_temp_free_i32(oi);
        tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
#else
        /* Restart with exclusive lock.  */
        gen_helper_exit_atomic(cpu_env);
        ctx->base.is_jmp = DISAS_NORETURN;
#endif
    } else if (ctx->le_mode) {
        tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEQ);
T
Tom Musta 已提交
2642
        gen_addr_add(ctx, EA, EA, 8);
2643
        tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_LEQ);
T
Tom Musta 已提交
2644
    } else {
2645
        tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_BEQ);
T
Tom Musta 已提交
2646
        gen_addr_add(ctx, EA, EA, 8);
2647
        tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_BEQ);
T
Tom Musta 已提交
2648
    }
A
aurel32 已提交
2649
    tcg_temp_free(EA);
2650
}
2651
#endif
B
bellard 已提交
2652 2653

/***                              Integer store                            ***/
2654
#define GEN_ST(name, stop, opc, type)                                         \
B
Blue Swirl 已提交
2655
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
2656
{                                                                             \
A
aurel32 已提交
2657 2658 2659 2660 2661
    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 已提交
2662
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2663 2664
}

2665
#define GEN_STU(name, stop, opc, type)                                        \
B
Blue Swirl 已提交
2666
static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
B
bellard 已提交
2667
{                                                                             \
A
aurel32 已提交
2668
    TCGv EA;                                                                  \
2669
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2670
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2671
        return;                                                               \
2672
    }                                                                         \
A
aurel32 已提交
2673
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2674
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2675
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2676
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2677
    else                                                                      \
A
aurel32 已提交
2678 2679
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2680 2681
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2682 2683
}

2684
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
B
Blue Swirl 已提交
2685
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
B
bellard 已提交
2686
{                                                                             \
A
aurel32 已提交
2687
    TCGv EA;                                                                  \
2688
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2689
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2690
        return;                                                               \
2691
    }                                                                         \
A
aurel32 已提交
2692
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2693
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2694 2695
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2696 2697
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2698 2699
}

2700
#define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk)                   \
2701
static void glue(gen_, name##x)(DisasContext *ctx)                            \
B
bellard 已提交
2702
{                                                                             \
A
aurel32 已提交
2703
    TCGv EA;                                                                  \
2704
    chk;                                                                      \
A
aurel32 已提交
2705 2706 2707 2708
    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 已提交
2709
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2710
}
2711
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
2712 2713 2714 2715
    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_NONE)

#define GEN_STX_HVRM(name, stop, opc2, opc3, type)                            \
    GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_HVRM)
B
bellard 已提交
2716

2717 2718 2719 2720 2721
#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 已提交
2722 2723

/* stb stbu stbux stbx */
2724
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
B
bellard 已提交
2725
/* sth sthu sthux sthx */
2726
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2727
/* stw stwu stwux stwx */
2728
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2729
#if defined(TARGET_PPC64)
2730 2731 2732
GEN_STUX(std, st64_i64, 0x15, 0x05, PPC_64B);
GEN_STX(std, st64_i64, 0x15, 0x04, PPC_64B);
GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST)
2733 2734 2735
GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
B
Blue Swirl 已提交
2736 2737

static void gen_std(DisasContext *ctx)
2738
{
2739
    int rs;
A
aurel32 已提交
2740
    TCGv EA;
2741 2742

    rs = rS(ctx->opcode);
T
Tom Musta 已提交
2743 2744 2745
    if ((ctx->opcode & 0x3) == 0x2) { /* stq */
        bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
        bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
2746
        TCGv hi, lo;
T
Tom Musta 已提交
2747

2748 2749 2750 2751
        if (!(ctx->insns_flags & PPC_64BX)) {
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        }

2752
        if (!legal_in_user_mode && ctx->pr) {
2753
            gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2754 2755
            return;
        }
T
Tom Musta 已提交
2756 2757

        if (!le_is_supported && ctx->le_mode) {
2758
            gen_align_no_le(ctx);
2759 2760
            return;
        }
T
Tom Musta 已提交
2761 2762 2763

        if (unlikely(rs & 1)) {
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2764 2765
            return;
        }
A
aurel32 已提交
2766
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2767
        EA = tcg_temp_new();
A
aurel32 已提交
2768
        gen_addr_imm_index(ctx, EA, 0x03);
T
Tom Musta 已提交
2769

2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791
        /* Note that the low part is always in RS+1, even in LE mode.  */
        lo = cpu_gpr[rs + 1];
        hi = cpu_gpr[rs];

        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
#ifdef CONFIG_ATOMIC128
            TCGv_i32 oi = tcg_temp_new_i32();
            if (ctx->le_mode) {
                tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
                gen_helper_stq_le_parallel(cpu_env, EA, lo, hi, oi);
            } else {
                tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
                gen_helper_stq_be_parallel(cpu_env, EA, lo, hi, oi);
            }
            tcg_temp_free_i32(oi);
#else
            /* Restart with exclusive lock.  */
            gen_helper_exit_atomic(cpu_env);
            ctx->base.is_jmp = DISAS_NORETURN;
#endif
        } else if (ctx->le_mode) {
            tcg_gen_qemu_st_i64(lo, EA, ctx->mem_idx, MO_LEQ);
T
Tom Musta 已提交
2792
            gen_addr_add(ctx, EA, EA, 8);
2793
            tcg_gen_qemu_st_i64(hi, EA, ctx->mem_idx, MO_LEQ);
T
Tom Musta 已提交
2794
        } else {
2795
            tcg_gen_qemu_st_i64(hi, EA, ctx->mem_idx, MO_BEQ);
T
Tom Musta 已提交
2796
            gen_addr_add(ctx, EA, EA, 8);
2797
            tcg_gen_qemu_st_i64(lo, EA, ctx->mem_idx, MO_BEQ);
T
Tom Musta 已提交
2798
        }
A
aurel32 已提交
2799
        tcg_temp_free(EA);
2800
    } else {
2801
        /* std / stdu */
2802 2803
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
A
aurel32 已提交
2804
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2805 2806 2807
                return;
            }
        }
A
aurel32 已提交
2808
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2809
        EA = tcg_temp_new();
A
aurel32 已提交
2810
        gen_addr_imm_index(ctx, EA, 0x03);
2811
        gen_qemu_st64_i64(ctx, cpu_gpr[rs], EA);
2812
        if (Rc(ctx->opcode))
A
aurel32 已提交
2813 2814
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
2815 2816 2817
    }
}
#endif
B
bellard 已提交
2818
/***                Integer load and store with byte reverse               ***/
2819

B
bellard 已提交
2820
/* lhbrx */
2821
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
A
aurel32 已提交
2822

B
bellard 已提交
2823
/* lwbrx */
2824
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
A
aurel32 已提交
2825

2826 2827
#if defined(TARGET_PPC64)
/* ldbrx */
2828
GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE);
2829 2830
/* stdbrx */
GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE);
2831 2832
#endif  /* TARGET_PPC64 */

B
bellard 已提交
2833
/* sthbrx */
2834
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
B
bellard 已提交
2835
/* stwbrx */
2836
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2837 2838

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

2840
/* lmw */
B
Blue Swirl 已提交
2841
static void gen_lmw(DisasContext *ctx)
B
bellard 已提交
2842
{
A
aurel32 已提交
2843 2844
    TCGv t0;
    TCGv_i32 t1;
2845 2846 2847 2848 2849

    if (ctx->le_mode) {
        gen_align_no_le(ctx);
        return;
    }
A
aurel32 已提交
2850 2851 2852 2853
    gen_set_access_type(ctx, ACCESS_INT);
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rD(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2854
    gen_helper_lmw(cpu_env, t0, t1);
2855 2856
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2857 2858 2859
}

/* stmw */
B
Blue Swirl 已提交
2860
static void gen_stmw(DisasContext *ctx)
B
bellard 已提交
2861
{
A
aurel32 已提交
2862 2863
    TCGv t0;
    TCGv_i32 t1;
2864 2865 2866 2867 2868

    if (ctx->le_mode) {
        gen_align_no_le(ctx);
        return;
    }
A
aurel32 已提交
2869 2870 2871 2872
    gen_set_access_type(ctx, ACCESS_INT);
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rS(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2873
    gen_helper_stmw(cpu_env, t0, t1);
2874 2875
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2876 2877 2878
}

/***                    Integer load and store strings                     ***/
2879

B
bellard 已提交
2880
/* lswi */
2881
/* PowerPC32 specification says we must generate an exception if
2882 2883 2884 2885
 * 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 已提交
2886
static void gen_lswi(DisasContext *ctx)
B
bellard 已提交
2887
{
2888 2889
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
2890 2891
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
2892
    int ra = rA(ctx->opcode);
B
bellard 已提交
2893 2894
    int nr;

2895 2896 2897 2898
    if (ctx->le_mode) {
        gen_align_no_le(ctx);
        return;
    }
B
bellard 已提交
2899 2900
    if (nb == 0)
        nb = 32;
M
Marc-André Lureau 已提交
2901
    nr = DIV_ROUND_UP(nb, 4);
2902
    if (unlikely(lsw_reg_in_range(start, nr, ra))) {
A
aurel32 已提交
2903
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
2904
        return;
B
bellard 已提交
2905
    }
A
aurel32 已提交
2906
    gen_set_access_type(ctx, ACCESS_INT);
2907
    t0 = tcg_temp_new();
A
aurel32 已提交
2908
    gen_addr_register(ctx, t0);
2909 2910
    t1 = tcg_const_i32(nb);
    t2 = tcg_const_i32(start);
2911
    gen_helper_lsw(cpu_env, t0, t1, t2);
2912 2913 2914
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
2915 2916 2917
}

/* lswx */
B
Blue Swirl 已提交
2918
static void gen_lswx(DisasContext *ctx)
B
bellard 已提交
2919
{
A
aurel32 已提交
2920 2921
    TCGv t0;
    TCGv_i32 t1, t2, t3;
2922 2923 2924 2925 2926

    if (ctx->le_mode) {
        gen_align_no_le(ctx);
        return;
    }
A
aurel32 已提交
2927 2928 2929 2930 2931 2932
    gen_set_access_type(ctx, ACCESS_INT);
    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));
2933
    gen_helper_lswx(cpu_env, t0, t1, t2, t3);
2934 2935 2936 2937
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
B
bellard 已提交
2938 2939 2940
}

/* stswi */
B
Blue Swirl 已提交
2941
static void gen_stswi(DisasContext *ctx)
B
bellard 已提交
2942
{
A
aurel32 已提交
2943 2944
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
2945
    int nb = NB(ctx->opcode);
2946 2947 2948 2949 2950

    if (ctx->le_mode) {
        gen_align_no_le(ctx);
        return;
    }
A
aurel32 已提交
2951 2952 2953
    gen_set_access_type(ctx, ACCESS_INT);
    t0 = tcg_temp_new();
    gen_addr_register(ctx, t0);
B
bellard 已提交
2954 2955
    if (nb == 0)
        nb = 32;
2956
    t1 = tcg_const_i32(nb);
A
aurel32 已提交
2957
    t2 = tcg_const_i32(rS(ctx->opcode));
2958
    gen_helper_stsw(cpu_env, t0, t1, t2);
2959 2960 2961
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
2962 2963 2964
}

/* stswx */
B
Blue Swirl 已提交
2965
static void gen_stswx(DisasContext *ctx)
B
bellard 已提交
2966
{
A
aurel32 已提交
2967 2968
    TCGv t0;
    TCGv_i32 t1, t2;
2969 2970 2971 2972 2973

    if (ctx->le_mode) {
        gen_align_no_le(ctx);
        return;
    }
A
aurel32 已提交
2974 2975 2976 2977
    gen_set_access_type(ctx, ACCESS_INT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_temp_new_i32();
2978 2979
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
    tcg_gen_andi_i32(t1, t1, 0x7F);
A
aurel32 已提交
2980
    t2 = tcg_const_i32(rS(ctx->opcode));
2981
    gen_helper_stsw(cpu_env, t0, t1, t2);
2982 2983 2984
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
2985 2986 2987 2988
}

/***                        Memory synchronisation                         ***/
/* eieio */
B
Blue Swirl 已提交
2989
static void gen_eieio(DisasContext *ctx)
B
bellard 已提交
2990
{
2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012
    TCGBar bar = TCG_MO_LD_ST;

    /*
     * POWER9 has a eieio instruction variant using bit 6 as a hint to
     * tell the CPU it is a store-forwarding barrier.
     */
    if (ctx->opcode & 0x2000000) {
        /*
         * ISA says that "Reserved fields in instructions are ignored
         * by the processor". So ignore the bit 6 on non-POWER9 CPU but
         * as this is not an instruction software should be using,
         * complain to the user.
         */
        if (!(ctx->insns_flags2 & PPC2_ISA300)) {
            qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
                          TARGET_FMT_lx "\n", ctx->base.pc_next - 4);
        } else {
            bar = TCG_MO_ST_LD;
        }
    }

    tcg_gen_mb(bar | TCG_BAR_SC);
B
bellard 已提交
3013 3014
}

3015
#if !defined(CONFIG_USER_ONLY)
3016
static inline void gen_check_tlb_flush(DisasContext *ctx, bool global)
3017
{
3018 3019
    TCGv_i32 t;
    TCGLabel *l;
3020

3021 3022 3023 3024 3025
    if (!ctx->lazy_tlb_flush) {
        return;
    }
    l = gen_new_label();
    t = tcg_temp_new_i32();
3026 3027
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
    tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, l);
3028 3029 3030 3031 3032
    if (global) {
        gen_helper_check_tlb_flush_global(cpu_env);
    } else {
        gen_helper_check_tlb_flush_local(cpu_env);
    }
3033 3034 3035 3036
    gen_set_label(l);
    tcg_temp_free_i32(t);
}
#else
3037
static inline void gen_check_tlb_flush(DisasContext *ctx, bool global) { }
3038 3039
#endif

B
bellard 已提交
3040
/* isync */
B
Blue Swirl 已提交
3041
static void gen_isync(DisasContext *ctx)
B
bellard 已提交
3042
{
3043 3044 3045 3046 3047
    /*
     * We need to check for a pending TLB flush. This can only happen in
     * kernel mode however so check MSR_PR
     */
    if (!ctx->pr) {
3048
        gen_check_tlb_flush(ctx, false);
3049
    }
3050
    tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
A
aurel32 已提交
3051
    gen_stop_exception(ctx);
B
bellard 已提交
3052 3053
}

3054 3055
#define MEMOP_GET_SIZE(x)  (1 << ((x) & MO_SIZE))

3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073
static void gen_load_locked(DisasContext *ctx, TCGMemOp memop)
{
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
    TCGv t0 = tcg_temp_new();

    gen_set_access_type(ctx, ACCESS_RES);
    gen_addr_reg_index(ctx, t0);
    tcg_gen_qemu_ld_tl(gpr, t0, ctx->mem_idx, memop | MO_ALIGN);
    tcg_gen_mov_tl(cpu_reserve, t0);
    tcg_gen_mov_tl(cpu_reserve_val, gpr);
    tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
    tcg_temp_free(t0);
}

#define LARX(name, memop)                  \
static void gen_##name(DisasContext *ctx)  \
{                                          \
    gen_load_locked(ctx, memop);           \
B
bellard 已提交
3074 3075
}

3076
/* lwarx */
3077 3078 3079
LARX(lbarx, DEF_MEMOP(MO_UB))
LARX(lharx, DEF_MEMOP(MO_UW))
LARX(lwarx, DEF_MEMOP(MO_UL))
3080

3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105
static void gen_ld_atomic(DisasContext *ctx, TCGMemOp memop)
{
    uint32_t gpr_FC = FC(ctx->opcode);
    TCGv EA = tcg_temp_new();
    TCGv src, dst;

    gen_addr_register(ctx, EA);
    dst = cpu_gpr[rD(ctx->opcode)];
    src = cpu_gpr[rD(ctx->opcode) + 1];

    memop |= MO_ALIGN;
    switch (gpr_FC) {
    case 0: /* Fetch and add */
        tcg_gen_atomic_fetch_add_tl(dst, EA, src, ctx->mem_idx, memop);
        break;
    case 1: /* Fetch and xor */
        tcg_gen_atomic_fetch_xor_tl(dst, EA, src, ctx->mem_idx, memop);
        break;
    case 2: /* Fetch and or */
        tcg_gen_atomic_fetch_or_tl(dst, EA, src, ctx->mem_idx, memop);
        break;
    case 3: /* Fetch and 'and' */
        tcg_gen_atomic_fetch_and_tl(dst, EA, src, ctx->mem_idx, memop);
        break;
    case 4:  /* Fetch and max unsigned */
3106 3107
        tcg_gen_atomic_fetch_umax_tl(dst, EA, src, ctx->mem_idx, memop);
        break;
3108
    case 5:  /* Fetch and max signed */
3109 3110
        tcg_gen_atomic_fetch_smax_tl(dst, EA, src, ctx->mem_idx, memop);
        break;
3111
    case 6:  /* Fetch and min unsigned */
3112 3113
        tcg_gen_atomic_fetch_umin_tl(dst, EA, src, ctx->mem_idx, memop);
        break;
3114
    case 7:  /* Fetch and min signed */
3115 3116 3117 3118 3119
        tcg_gen_atomic_fetch_smin_tl(dst, EA, src, ctx->mem_idx, memop);
        break;
    case 8: /* Swap */
        tcg_gen_atomic_xchg_tl(dst, EA, src, ctx->mem_idx, memop);
        break;
3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142
    case 16: /* compare and swap not equal */
    case 24: /* Fetch and increment bounded */
    case 25: /* Fetch and increment equal */
    case 28: /* Fetch and decrement bounded */
        gen_invalid(ctx);
        break;
    default:
        /* invoke data storage error handler */
        gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
    }
    tcg_temp_free(EA);
}

static void gen_lwat(DisasContext *ctx)
{
    gen_ld_atomic(ctx, DEF_MEMOP(MO_UL));
}

#ifdef TARGET_PPC64
static void gen_ldat(DisasContext *ctx)
{
    gen_ld_atomic(ctx, DEF_MEMOP(MO_Q));
}
3143 3144
#endif

3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169
static void gen_st_atomic(DisasContext *ctx, TCGMemOp memop)
{
    uint32_t gpr_FC = FC(ctx->opcode);
    TCGv EA = tcg_temp_new();
    TCGv src, discard;

    gen_addr_register(ctx, EA);
    src = cpu_gpr[rD(ctx->opcode)];
    discard = tcg_temp_new();

    memop |= MO_ALIGN;
    switch (gpr_FC) {
    case 0: /* add and Store */
        tcg_gen_atomic_add_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
        break;
    case 1: /* xor and Store */
        tcg_gen_atomic_xor_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
        break;
    case 2: /* Or and Store */
        tcg_gen_atomic_or_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
        break;
    case 3: /* 'and' and Store */
        tcg_gen_atomic_and_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
        break;
    case 4:  /* Store max unsigned */
3170 3171
        tcg_gen_atomic_umax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
        break;
3172
    case 5:  /* Store max signed */
3173 3174
        tcg_gen_atomic_smax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
        break;
3175
    case 6:  /* Store min unsigned */
3176 3177
        tcg_gen_atomic_umin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
        break;
3178
    case 7:  /* Store min signed */
3179 3180
        tcg_gen_atomic_smin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
        break;
3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201
    case 24: /* Store twin  */
        gen_invalid(ctx);
        break;
    default:
        /* invoke data storage error handler */
        gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
    }
    tcg_temp_free(discard);
    tcg_temp_free(EA);
}

static void gen_stwat(DisasContext *ctx)
{
    gen_st_atomic(ctx, DEF_MEMOP(MO_UL));
}

#ifdef TARGET_PPC64
static void gen_stdat(DisasContext *ctx)
{
    gen_st_atomic(ctx, DEF_MEMOP(MO_Q));
}
3202 3203
#endif

3204
static void gen_conditional_store(DisasContext *ctx, TCGMemOp memop)
3205
{
3206 3207
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
3208 3209
    TCGv t0 = tcg_temp_new();
    int reg = rS(ctx->opcode);
3210

3211 3212 3213 3214
    gen_set_access_type(ctx, ACCESS_RES);
    gen_addr_reg_index(ctx, t0);
    tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
    tcg_temp_free(t0);
3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226

    t0 = tcg_temp_new();
    tcg_gen_atomic_cmpxchg_tl(t0, cpu_reserve, cpu_reserve_val,
                              cpu_gpr[reg], ctx->mem_idx,
                              DEF_MEMOP(memop) | MO_ALIGN);
    tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_reserve_val);
    tcg_gen_shli_tl(t0, t0, CRF_EQ_BIT);
    tcg_gen_or_tl(t0, t0, cpu_so);
    tcg_gen_trunc_tl_i32(cpu_crf[0], t0);
    tcg_temp_free(t0);
    tcg_gen_br(l2);

3227
    gen_set_label(l1);
3228 3229 3230 3231

    /* Address mismatch implies failure.  But we still need to provide the
       memory barrier semantics of the instruction.  */
    tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
3232 3233 3234
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);

    gen_set_label(l2);
3235 3236 3237
    tcg_gen_movi_tl(cpu_reserve, -1);
}

3238 3239 3240 3241
#define STCX(name, memop)                  \
static void gen_##name(DisasContext *ctx)  \
{                                          \
    gen_conditional_store(ctx, memop);     \
3242 3243 3244 3245 3246
}

STCX(stbcx_, DEF_MEMOP(MO_UB))
STCX(sthcx_, DEF_MEMOP(MO_UW))
STCX(stwcx_, DEF_MEMOP(MO_UL))
3247

J
j_mayer 已提交
3248 3249
#if defined(TARGET_PPC64)
/* ldarx */
3250
LARX(ldarx, DEF_MEMOP(MO_Q))
3251 3252
/* stdcx. */
STCX(stdcx_, DEF_MEMOP(MO_Q))
J
j_mayer 已提交
3253

3254 3255 3256 3257
/* lqarx */
static void gen_lqarx(DisasContext *ctx)
{
    int rd = rD(ctx->opcode);
3258
    TCGv EA, hi, lo;
3259 3260 3261 3262 3263 3264 3265 3266

    if (unlikely((rd & 1) || (rd == rA(ctx->opcode)) ||
                 (rd == rB(ctx->opcode)))) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        return;
    }

    gen_set_access_type(ctx, ACCESS_RES);
3267
    EA = tcg_temp_new();
3268
    gen_addr_reg_index(ctx, EA);
3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299

    /* Note that the low part is always in RD+1, even in LE mode.  */
    lo = cpu_gpr[rd + 1];
    hi = cpu_gpr[rd];

    if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
#ifdef CONFIG_ATOMIC128
        TCGv_i32 oi = tcg_temp_new_i32();
        if (ctx->le_mode) {
            tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ | MO_ALIGN_16,
                                                ctx->mem_idx));
            gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
        } else {
            tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ | MO_ALIGN_16,
                                                ctx->mem_idx));
            gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
        }
        tcg_temp_free_i32(oi);
        tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
#else
        /* Restart with exclusive lock.  */
        gen_helper_exit_atomic(cpu_env);
        ctx->base.is_jmp = DISAS_NORETURN;
        tcg_temp_free(EA);
        return;
#endif
    } else if (ctx->le_mode) {
        tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEQ | MO_ALIGN_16);
        tcg_gen_mov_tl(cpu_reserve, EA);
        gen_addr_add(ctx, EA, EA, 8);
        tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_LEQ);
3300
    } else {
3301 3302 3303 3304
        tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_BEQ | MO_ALIGN_16);
        tcg_gen_mov_tl(cpu_reserve, EA);
        gen_addr_add(ctx, EA, EA, 8);
        tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_BEQ);
3305 3306
    }
    tcg_temp_free(EA);
3307 3308 3309

    tcg_gen_st_tl(hi, cpu_env, offsetof(CPUPPCState, reserve_val));
    tcg_gen_st_tl(lo, cpu_env, offsetof(CPUPPCState, reserve_val2));
3310 3311
}

3312 3313 3314
/* stqcx. */
static void gen_stqcx_(DisasContext *ctx)
{
3315 3316
    int rs = rS(ctx->opcode);
    TCGv EA, hi, lo;
3317

3318
    if (unlikely(rs & 1)) {
3319 3320 3321
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        return;
    }
3322

3323
    gen_set_access_type(ctx, ACCESS_RES);
3324
    EA = tcg_temp_new();
3325 3326
    gen_addr_reg_index(ctx, EA);

3327 3328 3329
    /* Note that the low part is always in RS+1, even in LE mode.  */
    lo = cpu_gpr[rs + 1];
    hi = cpu_gpr[rs];
3330

3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345
    if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
        TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_Q) | MO_ALIGN_16);
#ifdef CONFIG_ATOMIC128
        if (ctx->le_mode) {
            gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env, EA, lo, hi, oi);
        } else {
            gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env, EA, lo, hi, oi);
        }
#else
        /* Restart with exclusive lock.  */
        gen_helper_exit_atomic(cpu_env);
        ctx->base.is_jmp = DISAS_NORETURN;
#endif
        tcg_temp_free(EA);
        tcg_temp_free_i32(oi);
3346
    } else {
3347 3348 3349 3350
        TCGLabel *lab_fail = gen_new_label();
        TCGLabel *lab_over = gen_new_label();
        TCGv_i64 t0 = tcg_temp_new_i64();
        TCGv_i64 t1 = tcg_temp_new_i64();
3351

3352 3353
        tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, lab_fail);
        tcg_temp_free(EA);
3354

3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385
        gen_qemu_ld64_i64(ctx, t0, cpu_reserve);
        tcg_gen_ld_i64(t1, cpu_env, (ctx->le_mode
                                     ? offsetof(CPUPPCState, reserve_val2)
                                     : offsetof(CPUPPCState, reserve_val)));
        tcg_gen_brcond_i64(TCG_COND_NE, t0, t1, lab_fail);

        tcg_gen_addi_i64(t0, cpu_reserve, 8);
        gen_qemu_ld64_i64(ctx, t0, t0);
        tcg_gen_ld_i64(t1, cpu_env, (ctx->le_mode
                                     ? offsetof(CPUPPCState, reserve_val)
                                     : offsetof(CPUPPCState, reserve_val2)));
        tcg_gen_brcond_i64(TCG_COND_NE, t0, t1, lab_fail);

        /* Success */
        gen_qemu_st64_i64(ctx, ctx->le_mode ? lo : hi, cpu_reserve);
        tcg_gen_addi_i64(t0, cpu_reserve, 8);
        gen_qemu_st64_i64(ctx, ctx->le_mode ? hi : lo, t0);

        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], CRF_EQ);
        tcg_gen_br(lab_over);

        gen_set_label(lab_fail);
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);

        gen_set_label(lab_over);
        tcg_gen_movi_tl(cpu_reserve, -1);
        tcg_temp_free_i64(t0);
        tcg_temp_free_i64(t1);
    }
}
J
j_mayer 已提交
3386 3387
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3388
/* sync */
B
Blue Swirl 已提交
3389
static void gen_sync(DisasContext *ctx)
B
bellard 已提交
3390
{
3391 3392 3393
    uint32_t l = (ctx->opcode >> 21) & 3;

    /*
3394 3395 3396 3397 3398 3399
     * We may need to check for a pending TLB flush.
     *
     * We do this on ptesync (l == 2) on ppc64 and any sync pn ppc32.
     *
     * Additionally, this can only happen in kernel mode however so
     * check MSR_PR as well.
3400
     */
3401
    if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
3402
        gen_check_tlb_flush(ctx, true);
3403
    }
3404
    tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
B
bellard 已提交
3405 3406
}

3407
/* wait */
B
Blue Swirl 已提交
3408
static void gen_wait(DisasContext *ctx)
3409
{
3410
    TCGv_i32 t0 = tcg_const_i32(1);
3411 3412
    tcg_gen_st_i32(t0, cpu_env,
                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
3413
    tcg_temp_free_i32(t0);
3414
    /* Stop translation, as the CPU is supposed to sleep from now */
3415
    gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
3416 3417
}

3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448
#if defined(TARGET_PPC64)
static void gen_doze(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    GEN_PRIV;
#else
    TCGv_i32 t;

    CHK_HV;
    t = tcg_const_i32(PPC_PM_DOZE);
    gen_helper_pminsn(cpu_env, t);
    tcg_temp_free_i32(t);
    gen_stop_exception(ctx);
#endif /* defined(CONFIG_USER_ONLY) */
}

static void gen_nap(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    GEN_PRIV;
#else
    TCGv_i32 t;

    CHK_HV;
    t = tcg_const_i32(PPC_PM_NAP);
    gen_helper_pminsn(cpu_env, t);
    tcg_temp_free_i32(t);
    gen_stop_exception(ctx);
#endif /* defined(CONFIG_USER_ONLY) */
}

3449 3450 3451 3452 3453
static void gen_stop(DisasContext *ctx)
{
    gen_nap(ctx);
}

3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484
static void gen_sleep(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    GEN_PRIV;
#else
    TCGv_i32 t;

    CHK_HV;
    t = tcg_const_i32(PPC_PM_SLEEP);
    gen_helper_pminsn(cpu_env, t);
    tcg_temp_free_i32(t);
    gen_stop_exception(ctx);
#endif /* defined(CONFIG_USER_ONLY) */
}

static void gen_rvwinkle(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    GEN_PRIV;
#else
    TCGv_i32 t;

    CHK_HV;
    t = tcg_const_i32(PPC_PM_RVWINKLE);
    gen_helper_pminsn(cpu_env, t);
    tcg_temp_free_i32(t);
    gen_stop_exception(ctx);
#endif /* defined(CONFIG_USER_ONLY) */
}
#endif /* #if defined(TARGET_PPC64) */

D
David Gibson 已提交
3485 3486 3487 3488 3489 3490 3491 3492
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
}

3493 3494 3495 3496 3497 3498 3499
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
{
    if (unlikely(ctx->singlestep_enabled)) {
        return false;
    }

#ifndef CONFIG_USER_ONLY
3500
    return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
3501 3502 3503 3504 3505
#else
    return true;
#endif
}

B
bellard 已提交
3506
/***                                Branch                                 ***/
3507
static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3508
{
3509
    if (NARROW_MODE(ctx)) {
3510
        dest = (uint32_t) dest;
3511
    }
3512
    if (use_goto_tb(ctx, dest)) {
B
bellard 已提交
3513
        tcg_gen_goto_tb(n);
3514
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3515
        tcg_gen_exit_tb(ctx->base.tb, n);
3516
    } else {
3517
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3518 3519
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3520
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
J
Julio Guerra 已提交
3521 3522
                (ctx->exception == POWERPC_EXCP_BRANCH ||
                 ctx->exception == POWERPC_EXCP_TRACE)) {
3523
                gen_exception_nip(ctx, POWERPC_EXCP_TRACE, dest);
3524 3525
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3526
                gen_debug_exception(ctx);
3527 3528
            }
        }
3529
        tcg_gen_lookup_and_goto_ptr();
3530
    }
B
bellard 已提交
3531 3532
}

B
Blue Swirl 已提交
3533
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3534
{
3535 3536 3537 3538
    if (NARROW_MODE(ctx)) {
        nip = (uint32_t)nip;
    }
    tcg_gen_movi_tl(cpu_lr, nip);
3539 3540
}

B
bellard 已提交
3541
/* b ba bl bla */
B
Blue Swirl 已提交
3542
static void gen_b(DisasContext *ctx)
B
bellard 已提交
3543
{
3544
    target_ulong li, target;
B
bellard 已提交
3545

3546
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3547
    /* sign extend LI */
3548 3549 3550
    li = LI(ctx->opcode);
    li = (li ^ 0x02000000) - 0x02000000;
    if (likely(AA(ctx->opcode) == 0)) {
3551
        target = ctx->base.pc_next + li - 4;
3552
    } else {
3553
        target = li;
3554 3555
    }
    if (LK(ctx->opcode)) {
3556
        gen_setlr(ctx, ctx->base.pc_next);
3557
    }
3558
    gen_update_cfar(ctx, ctx->base.pc_next - 4);
3559
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3560 3561
}

3562 3563 3564
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2
T
Tom Musta 已提交
3565
#define BCOND_TAR 3
3566

3567
static void gen_bcond(DisasContext *ctx, int type)
3568 3569
{
    uint32_t bo = BO(ctx->opcode);
3570
    TCGLabel *l1;
3571
    TCGv target;
3572

3573
    ctx->exception = POWERPC_EXCP_BRANCH;
T
Tom Musta 已提交
3574
    if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
P
pbrook 已提交
3575
        target = tcg_temp_local_new();
3576 3577
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
T
Tom Musta 已提交
3578 3579
        else if (type == BCOND_TAR)
            gen_load_spr(target, SPR_TAR);
3580 3581
        else
            tcg_gen_mov_tl(target, cpu_lr);
3582
    } else {
3583
        target = NULL;
3584
    }
3585
    if (LK(ctx->opcode))
3586
        gen_setlr(ctx, ctx->base.pc_next);
3587 3588 3589
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3590
        TCGv temp = tcg_temp_new();
3591
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3592
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3593 3594 3595
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3596
        if (NARROW_MODE(ctx)) {
3597
            tcg_gen_ext32u_tl(temp, cpu_ctr);
3598
        } else {
3599
            tcg_gen_mov_tl(temp, cpu_ctr);
3600
        }
3601 3602 3603 3604
        if (bo & 0x2) {
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
        } else {
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3605
        }
P
pbrook 已提交
3606
        tcg_temp_free(temp);
3607 3608 3609 3610
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
3611
        uint32_t mask = 0x08 >> (bi & 0x03);
P
pbrook 已提交
3612
        TCGv_i32 temp = tcg_temp_new_i32();
3613

3614
        if (bo & 0x8) {
3615 3616
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3617
        } else {
3618 3619
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3620
        }
P
pbrook 已提交
3621
        tcg_temp_free_i32(temp);
3622
    }
3623
    gen_update_cfar(ctx, ctx->base.pc_next - 4);
3624
    if (type == BCOND_IM) {
3625 3626
        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
        if (likely(AA(ctx->opcode) == 0)) {
3627
            gen_goto_tb(ctx, 0, ctx->base.pc_next + li - 4);
3628 3629 3630
        } else {
            gen_goto_tb(ctx, 0, li);
        }
3631
    } else {
3632
        if (NARROW_MODE(ctx)) {
3633
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3634
        } else {
3635
            tcg_gen_andi_tl(cpu_nip, target, ~3);
3636
        }
3637
        tcg_gen_lookup_and_goto_ptr();
3638 3639
        tcg_temp_free(target);
    }
3640 3641
    if ((bo & 0x14) != 0x14) {
        gen_set_label(l1);
3642
        gen_goto_tb(ctx, 1, ctx->base.pc_next);
3643
    }
3644 3645
}

B
Blue Swirl 已提交
3646
static void gen_bc(DisasContext *ctx)
3647
{
3648 3649 3650
    gen_bcond(ctx, BCOND_IM);
}

B
Blue Swirl 已提交
3651
static void gen_bcctr(DisasContext *ctx)
3652
{
3653 3654 3655
    gen_bcond(ctx, BCOND_CTR);
}

B
Blue Swirl 已提交
3656
static void gen_bclr(DisasContext *ctx)
3657
{
3658 3659
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3660

T
Tom Musta 已提交
3661 3662 3663 3664 3665
static void gen_bctar(DisasContext *ctx)
{
    gen_bcond(ctx, BCOND_TAR);
}

B
bellard 已提交
3666
/***                      Condition register logical                       ***/
3667
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
B
Blue Swirl 已提交
3668
static void glue(gen_, name)(DisasContext *ctx)                                       \
B
bellard 已提交
3669
{                                                                             \
3670 3671
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
P
pbrook 已提交
3672
    TCGv_i32 t0, t1;                                                          \
3673
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
P
pbrook 已提交
3674
    t0 = tcg_temp_new_i32();                                                  \
3675
    if (sh > 0)                                                               \
3676
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3677
    else if (sh < 0)                                                          \
3678
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3679
    else                                                                      \
3680
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
P
pbrook 已提交
3681
    t1 = tcg_temp_new_i32();                                                  \
3682 3683
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3684
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3685
    else if (sh < 0)                                                          \
3686
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3687
    else                                                                      \
3688 3689
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3690
    bitmask = 0x08 >> (crbD(ctx->opcode) & 0x03);                             \
3691 3692 3693
    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 已提交
3694 3695
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
B
bellard 已提交
3696 3697 3698
}

/* crand */
3699
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3700
/* crandc */
3701
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3702
/* creqv */
3703
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3704
/* crnand */
3705
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3706
/* crnor */
3707
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3708
/* cror */
3709
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3710
/* crorc */
3711
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3712
/* crxor */
3713
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
Blue Swirl 已提交
3714

3715
/* mcrf */
B
Blue Swirl 已提交
3716
static void gen_mcrf(DisasContext *ctx)
B
bellard 已提交
3717
{
A
aurel32 已提交
3718
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3719 3720 3721
}

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

3723
/* rfi (supervisor only) */
B
Blue Swirl 已提交
3724
static void gen_rfi(DisasContext *ctx)
B
bellard 已提交
3725
{
3726
#if defined(CONFIG_USER_ONLY)
3727
    GEN_PRIV;
3728
#else
3729 3730
    /* This instruction doesn't exist anymore on 64-bit server
     * processors compliant with arch 2.x
3731
     */
3732 3733 3734 3735
    if (ctx->insns_flags & PPC_SEGMENT_64B) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        return;
    }
3736
    /* Restore CPU state */
3737
    CHK_SV;
3738
    gen_update_cfar(ctx, ctx->base.pc_next - 4);
3739
    gen_helper_rfi(cpu_env);
A
aurel32 已提交
3740
    gen_sync_exception(ctx);
3741
#endif
B
bellard 已提交
3742 3743
}

J
j_mayer 已提交
3744
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
3745
static void gen_rfid(DisasContext *ctx)
J
j_mayer 已提交
3746 3747
{
#if defined(CONFIG_USER_ONLY)
3748
    GEN_PRIV;
J
j_mayer 已提交
3749 3750
#else
    /* Restore CPU state */
3751
    CHK_SV;
3752
    gen_update_cfar(ctx, ctx->base.pc_next - 4);
3753
    gen_helper_rfid(cpu_env);
A
aurel32 已提交
3754
    gen_sync_exception(ctx);
J
j_mayer 已提交
3755 3756 3757
#endif
}

B
Blue Swirl 已提交
3758
static void gen_hrfid(DisasContext *ctx)
3759 3760
{
#if defined(CONFIG_USER_ONLY)
3761
    GEN_PRIV;
3762 3763
#else
    /* Restore CPU state */
3764
    CHK_HV;
3765
    gen_helper_hrfid(cpu_env);
A
aurel32 已提交
3766
    gen_sync_exception(ctx);
3767 3768 3769 3770
#endif
}
#endif

B
bellard 已提交
3771
/* sc */
3772 3773 3774 3775 3776
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
B
Blue Swirl 已提交
3777
static void gen_sc(DisasContext *ctx)
B
bellard 已提交
3778
{
3779 3780 3781
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
A
aurel32 已提交
3782
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3783 3784 3785
}

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

3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801
/* Check for unconditional traps (always or never) */
static bool check_unconditional_trap(DisasContext *ctx)
{
    /* Trap never */
    if (TO(ctx->opcode) == 0) {
        return true;
    }
    /* Trap always */
    if (TO(ctx->opcode) == 31) {
        gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
        return true;
    }
    return false;
}

3802
/* tw */
B
Blue Swirl 已提交
3803
static void gen_tw(DisasContext *ctx)
B
bellard 已提交
3804
{
3805 3806 3807 3808 3809 3810
    TCGv_i32 t0;

    if (check_unconditional_trap(ctx)) {
        return;
    }
    t0 = tcg_const_i32(TO(ctx->opcode));
3811 3812
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3813
    tcg_temp_free_i32(t0);
B
bellard 已提交
3814 3815 3816
}

/* twi */
B
Blue Swirl 已提交
3817
static void gen_twi(DisasContext *ctx)
B
bellard 已提交
3818
{
3819 3820 3821 3822 3823 3824 3825 3826
    TCGv t0;
    TCGv_i32 t1;

    if (check_unconditional_trap(ctx)) {
        return;
    }
    t0 = tcg_const_tl(SIMM(ctx->opcode));
    t1 = tcg_const_i32(TO(ctx->opcode));
3827
    gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3828 3829
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3830 3831
}

3832 3833
#if defined(TARGET_PPC64)
/* td */
B
Blue Swirl 已提交
3834
static void gen_td(DisasContext *ctx)
3835
{
3836 3837 3838 3839 3840 3841
    TCGv_i32 t0;

    if (check_unconditional_trap(ctx)) {
        return;
    }
    t0 = tcg_const_i32(TO(ctx->opcode));
3842 3843
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                  t0);
3844
    tcg_temp_free_i32(t0);
3845 3846 3847
}

/* tdi */
B
Blue Swirl 已提交
3848
static void gen_tdi(DisasContext *ctx)
3849
{
3850 3851 3852 3853 3854 3855 3856 3857
    TCGv t0;
    TCGv_i32 t1;

    if (check_unconditional_trap(ctx)) {
        return;
    }
    t0 = tcg_const_tl(SIMM(ctx->opcode));
    t1 = tcg_const_i32(TO(ctx->opcode));
3858
    gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
3859 3860
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
3861 3862 3863
}
#endif

B
bellard 已提交
3864
/***                          Processor control                            ***/
B
Blue Swirl 已提交
3865

3866
static void gen_read_xer(DisasContext *ctx, TCGv dst)
3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877
{
    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);
3878 3879 3880 3881 3882 3883
    if (is_isa300(ctx)) {
        tcg_gen_shli_tl(t0, cpu_ov32, XER_OV32);
        tcg_gen_or_tl(dst, dst, t0);
        tcg_gen_shli_tl(t0, cpu_ca32, XER_CA32);
        tcg_gen_or_tl(dst, dst, t0);
    }
3884 3885 3886 3887 3888 3889 3890
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
}

static void gen_write_xer(TCGv src)
{
3891
    /* Write all flags, while reading back check for isa300 */
3892
    tcg_gen_andi_tl(cpu_xer, src,
3893 3894 3895 3896 3897
                    ~((1u << XER_SO) |
                      (1u << XER_OV) | (1u << XER_OV32) |
                      (1u << XER_CA) | (1u << XER_CA32)));
    tcg_gen_extract_tl(cpu_ov32, src, XER_OV32, 1);
    tcg_gen_extract_tl(cpu_ca32, src, XER_CA32, 1);
3898 3899 3900
    tcg_gen_extract_tl(cpu_so, src, XER_SO, 1);
    tcg_gen_extract_tl(cpu_ov, src, XER_OV, 1);
    tcg_gen_extract_tl(cpu_ca, src, XER_CA, 1);
3901 3902
}

3903
/* mcrxr */
B
Blue Swirl 已提交
3904
static void gen_mcrxr(DisasContext *ctx)
B
bellard 已提交
3905
{
3906 3907 3908 3909 3910 3911 3912
    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);
3913 3914 3915
    tcg_gen_shli_i32(t0, t0, 3);
    tcg_gen_shli_i32(t1, t1, 2);
    tcg_gen_shli_i32(dst, dst, 1);
3916 3917 3918 3919 3920 3921 3922 3923
    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 已提交
3924 3925
}

3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947
#ifdef TARGET_PPC64
/* mcrxrx */
static void gen_mcrxrx(DisasContext *ctx)
{
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];

    /* copy OV and OV32 */
    tcg_gen_shli_tl(t0, cpu_ov, 1);
    tcg_gen_or_tl(t0, t0, cpu_ov32);
    tcg_gen_shli_tl(t0, t0, 2);
    /* copy CA and CA32 */
    tcg_gen_shli_tl(t1, cpu_ca, 1);
    tcg_gen_or_tl(t1, t1, cpu_ca32);
    tcg_gen_or_tl(t0, t0, t1);
    tcg_gen_trunc_tl_i32(dst, t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
}
#endif

A
aurel32 已提交
3948
/* mfcr mfocrf */
B
Blue Swirl 已提交
3949
static void gen_mfcr(DisasContext *ctx)
B
bellard 已提交
3950
{
3951
    uint32_t crm, crn;
3952

3953 3954
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3955
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3956
            crn = ctz32 (crm);
3957
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3958 3959
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3960
        }
3961
    } else {
A
aurel32 已提交
3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979
        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);
3980
    }
B
bellard 已提交
3981 3982 3983
}

/* mfmsr */
B
Blue Swirl 已提交
3984
static void gen_mfmsr(DisasContext *ctx)
B
bellard 已提交
3985
{
3986
    CHK_SV;
3987
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
B
bellard 已提交
3988 3989
}

3990
static void spr_noaccess(DisasContext *ctx, int gprn, int sprn)
3991
{
3992
#if 0
3993 3994
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
3995
#endif
3996 3997 3998
}
#define SPR_NOACCESS (&spr_noaccess)

B
bellard 已提交
3999
/* mfspr */
B
Blue Swirl 已提交
4000
static inline void gen_op_mfspr(DisasContext *ctx)
B
bellard 已提交
4001
{
4002
    void (*read_cb)(DisasContext *ctx, int gprn, int sprn);
B
bellard 已提交
4003 4004
    uint32_t sprn = SPR(ctx->opcode);

4005 4006 4007 4008 4009 4010
#if defined(CONFIG_USER_ONLY)
    read_cb = ctx->spr_cb[sprn].uea_read;
#else
    if (ctx->pr) {
        read_cb = ctx->spr_cb[sprn].uea_read;
    } else if (ctx->hv) {
4011
        read_cb = ctx->spr_cb[sprn].hea_read;
4012
    } else {
4013
        read_cb = ctx->spr_cb[sprn].oea_read;
4014
    }
4015
#endif
4016 4017
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
4018
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
4019 4020
        } else {
            /* Privilege exception */
4021 4022 4023 4024 4025
            /* 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) {
4026 4027 4028
                qemu_log_mask(LOG_GUEST_ERROR, "Trying to read privileged spr "
                              "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
                              ctx->base.pc_next - 4);
4029
            }
4030
            gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
4031
        }
4032
    } else {
4033 4034 4035 4036 4037 4038
        /* ISA 2.07 defines these as no-ops */
        if ((ctx->insns_flags2 & PPC2_ISA207S) &&
            (sprn >= 808 && sprn <= 811)) {
            /* This is a nop */
            return;
        }
4039
        /* Not defined */
4040 4041 4042
        qemu_log_mask(LOG_GUEST_ERROR,
                      "Trying to read invalid spr %d (0x%03x) at "
                      TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054

        /* The behaviour depends on MSR:PR and SPR# bit 0x10,
         * it can generate a priv, a hv emu or a no-op
         */
        if (sprn & 0x10) {
            if (ctx->pr) {
                gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
            }
        } else {
            if (ctx->pr || sprn == 0 || sprn == 4 || sprn == 5 || sprn == 6) {
                gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
            }
4055
        }
B
bellard 已提交
4056 4057 4058
    }
}

B
Blue Swirl 已提交
4059
static void gen_mfspr(DisasContext *ctx)
B
bellard 已提交
4060
{
4061
    gen_op_mfspr(ctx);
4062
}
4063 4064

/* mftb */
B
Blue Swirl 已提交
4065
static void gen_mftb(DisasContext *ctx)
4066 4067
{
    gen_op_mfspr(ctx);
B
bellard 已提交
4068 4069
}

A
aurel32 已提交
4070
/* mtcrf mtocrf*/
B
Blue Swirl 已提交
4071
static void gen_mtcrf(DisasContext *ctx)
B
bellard 已提交
4072
{
4073
    uint32_t crm, crn;
4074

4075
    crm = CRM(ctx->opcode);
M
malc 已提交
4076 4077 4078
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
4079
            crn = ctz32 (crm);
M
malc 已提交
4080
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
4081 4082
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
4083 4084
            tcg_temp_free_i32(temp);
        }
4085
    } else {
A
aurel32 已提交
4086 4087 4088 4089 4090 4091 4092 4093
        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 已提交
4094
        tcg_temp_free_i32(temp);
4095
    }
B
bellard 已提交
4096 4097 4098
}

/* mtmsr */
J
j_mayer 已提交
4099
#if defined(TARGET_PPC64)
B
Blue Swirl 已提交
4100
static void gen_mtmsrd(DisasContext *ctx)
J
j_mayer 已提交
4101
{
4102 4103 4104
    CHK_SV;

#if !defined(CONFIG_USER_ONLY)
4105 4106
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
4107 4108
        TCGv t0 = tcg_temp_new();
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
4109
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
4110 4111
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
        tcg_temp_free(t0);
4112
    } else {
4113 4114 4115 4116
        /* 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
         */
4117
        gen_update_nip(ctx, ctx->base.pc_next);
4118
        gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
4119 4120
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
4121
        gen_stop_exception(ctx);
4122
    }
4123
#endif /* !defined(CONFIG_USER_ONLY) */
J
j_mayer 已提交
4124
}
4125
#endif /* defined(TARGET_PPC64) */
J
j_mayer 已提交
4126

B
Blue Swirl 已提交
4127
static void gen_mtmsr(DisasContext *ctx)
B
bellard 已提交
4128
{
4129 4130 4131 4132
    CHK_SV;

#if !defined(CONFIG_USER_ONLY)
   if (ctx->opcode & 0x00010000) {
4133
        /* Special form that does not need any synchronisation */
4134 4135
        TCGv t0 = tcg_temp_new();
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
4136
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
4137 4138
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
        tcg_temp_free(t0);
4139
    } else {
4140 4141
        TCGv msr = tcg_temp_new();

4142 4143 4144 4145
        /* 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
         */
4146
        gen_update_nip(ctx, ctx->base.pc_next);
4147
#if defined(TARGET_PPC64)
4148 4149 4150
        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)]);
4151
#endif
4152
        gen_helper_store_msr(cpu_env, msr);
4153
        tcg_temp_free(msr);
4154
        /* Must stop the translation as machine state (may have) changed */
4155
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
4156
        gen_stop_exception(ctx);
4157
    }
4158
#endif
B
bellard 已提交
4159 4160 4161
}

/* mtspr */
B
Blue Swirl 已提交
4162
static void gen_mtspr(DisasContext *ctx)
B
bellard 已提交
4163
{
4164
    void (*write_cb)(DisasContext *ctx, int sprn, int gprn);
B
bellard 已提交
4165 4166
    uint32_t sprn = SPR(ctx->opcode);

4167 4168 4169 4170 4171 4172
#if defined(CONFIG_USER_ONLY)
    write_cb = ctx->spr_cb[sprn].uea_write;
#else
    if (ctx->pr) {
        write_cb = ctx->spr_cb[sprn].uea_write;
    } else if (ctx->hv) {
4173
        write_cb = ctx->spr_cb[sprn].hea_write;
4174
    } else {
4175
        write_cb = ctx->spr_cb[sprn].oea_write;
4176
    }
4177
#endif
4178 4179
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
4180
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
4181 4182
        } else {
            /* Privilege exception */
4183 4184 4185
            qemu_log_mask(LOG_GUEST_ERROR, "Trying to write privileged spr "
                          "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
                          ctx->base.pc_next - 4);
4186
            gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
4187
        }
4188
    } else {
4189 4190 4191 4192 4193 4194 4195
        /* ISA 2.07 defines these as no-ops */
        if ((ctx->insns_flags2 & PPC2_ISA207S) &&
            (sprn >= 808 && sprn <= 811)) {
            /* This is a nop */
            return;
        }

4196
        /* Not defined */
4197 4198 4199
        qemu_log_mask(LOG_GUEST_ERROR,
                      "Trying to write invalid spr %d (0x%03x) at "
                      TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
4200

4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212

        /* The behaviour depends on MSR:PR and SPR# bit 0x10,
         * it can generate a priv, a hv emu or a no-op
         */
        if (sprn & 0x10) {
            if (ctx->pr) {
                gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
            }
        } else {
            if (ctx->pr || sprn == 0) {
                gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
            }
4213
        }
B
bellard 已提交
4214 4215 4216
    }
}

4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237
#if defined(TARGET_PPC64)
/* setb */
static void gen_setb(DisasContext *ctx)
{
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv_i32 t8 = tcg_temp_new_i32();
    TCGv_i32 tm1 = tcg_temp_new_i32();
    int crf = crfS(ctx->opcode);

    tcg_gen_setcondi_i32(TCG_COND_GEU, t0, cpu_crf[crf], 4);
    tcg_gen_movi_i32(t8, 8);
    tcg_gen_movi_i32(tm1, -1);
    tcg_gen_movcond_i32(TCG_COND_GEU, t0, cpu_crf[crf], t8, tm1, t0);
    tcg_gen_ext_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);

    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t8);
    tcg_temp_free_i32(tm1);
}
#endif

B
bellard 已提交
4238
/***                         Cache management                              ***/
B
Blue Swirl 已提交
4239

4240
/* dcbf */
B
Blue Swirl 已提交
4241
static void gen_dcbf(DisasContext *ctx)
B
bellard 已提交
4242
{
J
j_mayer 已提交
4243
    /* XXX: specification says this is treated as a load by the MMU */
A
aurel32 已提交
4244 4245 4246 4247 4248
    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);
4249
    tcg_temp_free(t0);
B
bellard 已提交
4250 4251 4252
}

/* dcbi (Supervisor only) */
B
Blue Swirl 已提交
4253
static void gen_dcbi(DisasContext *ctx)
B
bellard 已提交
4254
{
4255
#if defined(CONFIG_USER_ONLY)
4256
    GEN_PRIV;
4257
#else
A
aurel32 已提交
4258
    TCGv EA, val;
4259 4260

    CHK_SV;
P
pbrook 已提交
4261
    EA = tcg_temp_new();
A
aurel32 已提交
4262 4263
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
4264
    val = tcg_temp_new();
4265
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
4266 4267
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
4268 4269
    tcg_temp_free(val);
    tcg_temp_free(EA);
4270
#endif /* defined(CONFIG_USER_ONLY) */
B
bellard 已提交
4271 4272 4273
}

/* dcdst */
B
Blue Swirl 已提交
4274
static void gen_dcbst(DisasContext *ctx)
B
bellard 已提交
4275
{
4276
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
4277 4278 4279 4280 4281
    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);
4282
    tcg_temp_free(t0);
B
bellard 已提交
4283 4284 4285
}

/* dcbt */
B
Blue Swirl 已提交
4286
static void gen_dcbt(DisasContext *ctx)
B
bellard 已提交
4287
{
4288
    /* interpreted as no-op */
4289 4290 4291
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4292 4293 4294
}

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

A
Alexander Graf 已提交
4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313
/* dcbtls */
static void gen_dcbtls(DisasContext *ctx)
{
    /* Always fails locking the cache */
    TCGv t0 = tcg_temp_new();
    gen_load_spr(t0, SPR_Exxx_L1CSR0);
    tcg_gen_ori_tl(t0, t0, L1CSR0_CUL);
    gen_store_spr(SPR_Exxx_L1CSR0, t0);
    tcg_temp_free(t0);
}

B
bellard 已提交
4314
/* dcbz */
B
Blue Swirl 已提交
4315
static void gen_dcbz(DisasContext *ctx)
B
bellard 已提交
4316
{
A
Alexander Graf 已提交
4317
    TCGv tcgv_addr;
B
Benjamin Herrenschmidt 已提交
4318
    TCGv_i32 tcgv_op;
4319

A
aurel32 已提交
4320
    gen_set_access_type(ctx, ACCESS_CACHE);
A
Alexander Graf 已提交
4321
    tcgv_addr = tcg_temp_new();
B
Benjamin Herrenschmidt 已提交
4322
    tcgv_op = tcg_const_i32(ctx->opcode & 0x03FF000);
A
Alexander Graf 已提交
4323
    gen_addr_reg_index(ctx, tcgv_addr);
B
Benjamin Herrenschmidt 已提交
4324
    gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_op);
A
Alexander Graf 已提交
4325
    tcg_temp_free(tcgv_addr);
B
Benjamin Herrenschmidt 已提交
4326
    tcg_temp_free_i32(tcgv_op);
B
bellard 已提交
4327 4328
}

4329
/* dst / dstt */
B
Blue Swirl 已提交
4330
static void gen_dst(DisasContext *ctx)
4331 4332
{
    if (rA(ctx->opcode) == 0) {
4333
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
4334 4335 4336 4337 4338 4339
    } else {
        /* interpreted as no-op */
    }
}

/* dstst /dststt */
B
Blue Swirl 已提交
4340
static void gen_dstst(DisasContext *ctx)
4341 4342
{
    if (rA(ctx->opcode) == 0) {
4343
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
4344 4345 4346 4347 4348 4349 4350
    } else {
        /* interpreted as no-op */
    }

}

/* dss / dssall */
B
Blue Swirl 已提交
4351
static void gen_dss(DisasContext *ctx)
4352 4353 4354 4355
{
    /* interpreted as no-op */
}

B
bellard 已提交
4356
/* icbi */
B
Blue Swirl 已提交
4357
static void gen_icbi(DisasContext *ctx)
B
bellard 已提交
4358
{
A
aurel32 已提交
4359 4360 4361 4362
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4363
    gen_helper_icbi(cpu_env, t0);
4364
    tcg_temp_free(t0);
B
bellard 已提交
4365 4366 4367 4368
}

/* Optional: */
/* dcba */
B
Blue Swirl 已提交
4369
static void gen_dcba(DisasContext *ctx)
B
bellard 已提交
4370
{
4371 4372 4373 4374
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4375 4376 4377 4378
}

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

4380
/* mfsr */
B
Blue Swirl 已提交
4381
static void gen_mfsr(DisasContext *ctx)
B
bellard 已提交
4382
{
4383
#if defined(CONFIG_USER_ONLY)
4384
    GEN_PRIV;
4385
#else
4386
    TCGv t0;
4387 4388

    CHK_SV;
4389
    t0 = tcg_const_tl(SR(ctx->opcode));
4390
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4391
    tcg_temp_free(t0);
4392
#endif /* defined(CONFIG_USER_ONLY) */
B
bellard 已提交
4393 4394 4395
}

/* mfsrin */
B
Blue Swirl 已提交
4396
static void gen_mfsrin(DisasContext *ctx)
B
bellard 已提交
4397
{
4398
#if defined(CONFIG_USER_ONLY)
4399
    GEN_PRIV;
4400
#else
4401
    TCGv t0;
4402 4403

    CHK_SV;
4404
    t0 = tcg_temp_new();
4405
    tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
4406
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4407
    tcg_temp_free(t0);
4408
#endif /* defined(CONFIG_USER_ONLY) */
B
bellard 已提交
4409 4410 4411
}

/* mtsr */
B
Blue Swirl 已提交
4412
static void gen_mtsr(DisasContext *ctx)
B
bellard 已提交
4413
{
4414
#if defined(CONFIG_USER_ONLY)
4415
    GEN_PRIV;
4416
#else
4417
    TCGv t0;
4418 4419

    CHK_SV;
4420
    t0 = tcg_const_tl(SR(ctx->opcode));
4421
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4422
    tcg_temp_free(t0);
4423
#endif /* defined(CONFIG_USER_ONLY) */
B
bellard 已提交
4424 4425 4426
}

/* mtsrin */
B
Blue Swirl 已提交
4427
static void gen_mtsrin(DisasContext *ctx)
B
bellard 已提交
4428
{
4429
#if defined(CONFIG_USER_ONLY)
4430
    GEN_PRIV;
4431
#else
4432
    TCGv t0;
4433 4434
    CHK_SV;

4435
    t0 = tcg_temp_new();
4436
    tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
4437
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
4438
    tcg_temp_free(t0);
4439
#endif /* defined(CONFIG_USER_ONLY) */
B
bellard 已提交
4440 4441
}

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

4445
/* mfsr */
B
Blue Swirl 已提交
4446
static void gen_mfsr_64b(DisasContext *ctx)
4447 4448
{
#if defined(CONFIG_USER_ONLY)
4449
    GEN_PRIV;
4450
#else
4451
    TCGv t0;
4452 4453

    CHK_SV;
4454
    t0 = tcg_const_tl(SR(ctx->opcode));
4455
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4456
    tcg_temp_free(t0);
4457
#endif /* defined(CONFIG_USER_ONLY) */
4458 4459 4460
}

/* mfsrin */
B
Blue Swirl 已提交
4461
static void gen_mfsrin_64b(DisasContext *ctx)
4462 4463
{
#if defined(CONFIG_USER_ONLY)
4464
    GEN_PRIV;
4465
#else
4466
    TCGv t0;
4467 4468

    CHK_SV;
4469
    t0 = tcg_temp_new();
4470
    tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
4471
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4472
    tcg_temp_free(t0);
4473
#endif /* defined(CONFIG_USER_ONLY) */
4474 4475 4476
}

/* mtsr */
B
Blue Swirl 已提交
4477
static void gen_mtsr_64b(DisasContext *ctx)
4478 4479
{
#if defined(CONFIG_USER_ONLY)
4480
    GEN_PRIV;
4481
#else
4482
    TCGv t0;
4483 4484

    CHK_SV;
4485
    t0 = tcg_const_tl(SR(ctx->opcode));
4486
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4487
    tcg_temp_free(t0);
4488
#endif /* defined(CONFIG_USER_ONLY) */
4489 4490 4491
}

/* mtsrin */
B
Blue Swirl 已提交
4492
static void gen_mtsrin_64b(DisasContext *ctx)
4493 4494
{
#if defined(CONFIG_USER_ONLY)
4495
    GEN_PRIV;
4496
#else
4497
    TCGv t0;
4498 4499

    CHK_SV;
4500
    t0 = tcg_temp_new();
4501
    tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
4502
    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
4503
    tcg_temp_free(t0);
4504
#endif /* defined(CONFIG_USER_ONLY) */
4505
}
B
blueswir1 已提交
4506 4507

/* slbmte */
B
Blue Swirl 已提交
4508
static void gen_slbmte(DisasContext *ctx)
B
blueswir1 已提交
4509 4510
{
#if defined(CONFIG_USER_ONLY)
4511
    GEN_PRIV;
B
blueswir1 已提交
4512
#else
4513 4514
    CHK_SV;

4515 4516
    gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
4517
#endif /* defined(CONFIG_USER_ONLY) */
B
blueswir1 已提交
4518 4519
}

4520 4521 4522
static void gen_slbmfee(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
4523
    GEN_PRIV;
4524
#else
4525 4526
    CHK_SV;

4527
    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4528
                             cpu_gpr[rB(ctx->opcode)]);
4529
#endif /* defined(CONFIG_USER_ONLY) */
4530 4531 4532 4533 4534
}

static void gen_slbmfev(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
4535
    GEN_PRIV;
4536
#else
4537 4538
    CHK_SV;

4539
    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4540
                             cpu_gpr[rB(ctx->opcode)]);
4541
#endif /* defined(CONFIG_USER_ONLY) */
4542
}
4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560

static void gen_slbfee_(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
#else
    TCGLabel *l1, *l2;

    if (unlikely(ctx->pr)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
        return;
    }
    gen_helper_find_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
                             cpu_gpr[rB(ctx->opcode)]);
    l1 = gen_new_label();
    l2 = gen_new_label();
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rS(ctx->opcode)], -1, l1);
4561
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], CRF_EQ);
4562 4563 4564 4565 4566 4567
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_gpr[rS(ctx->opcode)], 0);
    gen_set_label(l2);
#endif
}
4568 4569
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4570
/***                      Lookaside buffer management                      ***/
4571
/* Optional & supervisor only: */
B
Blue Swirl 已提交
4572

4573
/* tlbia */
B
Blue Swirl 已提交
4574
static void gen_tlbia(DisasContext *ctx)
B
bellard 已提交
4575
{
4576
#if defined(CONFIG_USER_ONLY)
4577
    GEN_PRIV;
4578
#else
4579 4580
    CHK_HV;

4581
    gen_helper_tlbia(cpu_env);
4582
#endif  /* defined(CONFIG_USER_ONLY) */
B
bellard 已提交
4583 4584
}

B
blueswir1 已提交
4585
/* tlbiel */
B
Blue Swirl 已提交
4586
static void gen_tlbiel(DisasContext *ctx)
B
blueswir1 已提交
4587 4588
{
#if defined(CONFIG_USER_ONLY)
4589
    GEN_PRIV;
B
blueswir1 已提交
4590
#else
4591 4592
    CHK_SV;

4593
    gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4594
#endif /* defined(CONFIG_USER_ONLY) */
B
blueswir1 已提交
4595 4596
}

B
bellard 已提交
4597
/* tlbie */
B
Blue Swirl 已提交
4598
static void gen_tlbie(DisasContext *ctx)
B
bellard 已提交
4599
{
4600
#if defined(CONFIG_USER_ONLY)
4601
    GEN_PRIV;
4602
#else
4603
    TCGv_i32 t1;
4604 4605

    if (ctx->gtse) {
4606
        CHK_SV; /* If gtse is set then tlbie is supervisor privileged */
4607 4608 4609
    } else {
        CHK_HV; /* Else hypervisor privileged */
    }
4610

4611
    if (NARROW_MODE(ctx)) {
4612 4613
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4614
        gen_helper_tlbie(cpu_env, t0);
4615
        tcg_temp_free(t0);
4616
    } else {
4617
        gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4618
    }
4619 4620 4621 4622 4623
    t1 = tcg_temp_new_i32();
    tcg_gen_ld_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
    tcg_gen_ori_i32(t1, t1, TLB_NEED_GLOBAL_FLUSH);
    tcg_gen_st_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
    tcg_temp_free_i32(t1);
4624
#endif /* defined(CONFIG_USER_ONLY) */
B
bellard 已提交
4625 4626 4627
}

/* tlbsync */
B
Blue Swirl 已提交
4628
static void gen_tlbsync(DisasContext *ctx)
B
bellard 已提交
4629
{
4630
#if defined(CONFIG_USER_ONLY)
4631
    GEN_PRIV;
4632
#else
4633 4634 4635 4636 4637 4638

    if (ctx->gtse) {
        CHK_SV; /* If gtse is set then tlbsync is supervisor privileged */
    } else {
        CHK_HV; /* Else hypervisor privileged */
    }
4639

4640 4641 4642 4643
    /* BookS does both ptesync and tlbsync make tlbsync a nop for server */
    if (ctx->insns_flags & PPC_BOOKE) {
        gen_check_tlb_flush(ctx, true);
    }
4644
#endif /* defined(CONFIG_USER_ONLY) */
B
bellard 已提交
4645 4646
}

J
j_mayer 已提交
4647 4648
#if defined(TARGET_PPC64)
/* slbia */
B
Blue Swirl 已提交
4649
static void gen_slbia(DisasContext *ctx)
J
j_mayer 已提交
4650 4651
{
#if defined(CONFIG_USER_ONLY)
4652
    GEN_PRIV;
J
j_mayer 已提交
4653
#else
4654 4655
    CHK_SV;

4656
    gen_helper_slbia(cpu_env);
4657
#endif /* defined(CONFIG_USER_ONLY) */
J
j_mayer 已提交
4658 4659 4660
}

/* slbie */
B
Blue Swirl 已提交
4661
static void gen_slbie(DisasContext *ctx)
J
j_mayer 已提交
4662 4663
{
#if defined(CONFIG_USER_ONLY)
4664
    GEN_PRIV;
J
j_mayer 已提交
4665
#else
4666 4667
    CHK_SV;

4668
    gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
4669
#endif /* defined(CONFIG_USER_ONLY) */
J
j_mayer 已提交
4670
}
4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683

/* slbieg */
static void gen_slbieg(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    GEN_PRIV;
#else
    CHK_SV;

    gen_helper_slbieg(cpu_env, cpu_gpr[rB(ctx->opcode)]);
#endif /* defined(CONFIG_USER_ONLY) */
}

4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694
/* slbsync */
static void gen_slbsync(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    GEN_PRIV;
#else
    CHK_SV;
    gen_check_tlb_flush(ctx, true);
#endif /* defined(CONFIG_USER_ONLY) */
}

4695
#endif  /* defined(TARGET_PPC64) */
J
j_mayer 已提交
4696

B
bellard 已提交
4697 4698
/***                              External control                         ***/
/* Optional: */
B
Blue Swirl 已提交
4699

4700
/* eciwx */
B
Blue Swirl 已提交
4701
static void gen_eciwx(DisasContext *ctx)
B
bellard 已提交
4702
{
A
aurel32 已提交
4703
    TCGv t0;
4704
    /* Should check EAR[E] ! */
A
aurel32 已提交
4705 4706 4707
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4708 4709
    tcg_gen_qemu_ld_tl(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx,
                       DEF_MEMOP(MO_UL | MO_ALIGN));
4710
    tcg_temp_free(t0);
4711 4712 4713
}

/* ecowx */
B
Blue Swirl 已提交
4714
static void gen_ecowx(DisasContext *ctx)
4715
{
A
aurel32 已提交
4716
    TCGv t0;
4717
    /* Should check EAR[E] ! */
A
aurel32 已提交
4718 4719 4720
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4721 4722
    tcg_gen_qemu_st_tl(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx,
                       DEF_MEMOP(MO_UL | MO_ALIGN));
4723
    tcg_temp_free(t0);
4724 4725 4726
}

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

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

/* abso - abso. */
B
Blue Swirl 已提交
4744
static void gen_abso(DisasContext *ctx)
4745
{
4746 4747 4748
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
    TCGLabel *l3 = gen_new_label();
4749
    /* Start with XER OV disabled, the most likely case */
4750
    tcg_gen_movi_tl(cpu_ov, 0);
4751 4752
    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);
4753 4754
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4755 4756 4757 4758 4759 4760 4761
    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);
4762
    if (unlikely(Rc(ctx->opcode) != 0))
4763
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4764 4765 4766
}

/* clcs */
B
Blue Swirl 已提交
4767
static void gen_clcs(DisasContext *ctx)
4768
{
4769
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
B
Blue Swirl 已提交
4770
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
4771
    tcg_temp_free_i32(t0);
4772
    /* Rc=1 sets CR0 to an undefined state */
4773 4774 4775
}

/* div - div. */
B
Blue Swirl 已提交
4776
static void gen_div(DisasContext *ctx)
4777
{
4778 4779
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
4780
    if (unlikely(Rc(ctx->opcode) != 0))
4781
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4782 4783 4784
}

/* divo - divo. */
B
Blue Swirl 已提交
4785
static void gen_divo(DisasContext *ctx)
4786
{
4787 4788
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4789
    if (unlikely(Rc(ctx->opcode) != 0))
4790
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4791 4792 4793
}

/* divs - divs. */
B
Blue Swirl 已提交
4794
static void gen_divs(DisasContext *ctx)
4795
{
4796 4797
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rB(ctx->opcode)]);
4798
    if (unlikely(Rc(ctx->opcode) != 0))
4799
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4800 4801 4802
}

/* divso - divso. */
B
Blue Swirl 已提交
4803
static void gen_divso(DisasContext *ctx)
4804
{
4805 4806
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4807
    if (unlikely(Rc(ctx->opcode) != 0))
4808
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4809 4810 4811
}

/* doz - doz. */
B
Blue Swirl 已提交
4812
static void gen_doz(DisasContext *ctx)
4813
{
4814 4815
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
4816 4817 4818 4819 4820 4821
    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);
4822
    if (unlikely(Rc(ctx->opcode) != 0))
4823
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4824 4825 4826
}

/* dozo - dozo. */
B
Blue Swirl 已提交
4827
static void gen_dozo(DisasContext *ctx)
4828
{
4829 4830
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
4831 4832 4833 4834
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    /* Start with XER OV disabled, the most likely case */
4835
    tcg_gen_movi_tl(cpu_ov, 0);
4836 4837 4838 4839 4840 4841 4842
    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);
4843 4844
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4845 4846 4847 4848 4849 4850 4851
    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);
4852
    if (unlikely(Rc(ctx->opcode) != 0))
4853
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4854 4855 4856
}

/* dozi */
B
Blue Swirl 已提交
4857
static void gen_dozi(DisasContext *ctx)
4858
{
4859
    target_long simm = SIMM(ctx->opcode);
4860 4861
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
4862 4863 4864 4865 4866 4867 4868 4869
    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)]);
4870 4871 4872
}

/* lscbx - lscbx. */
B
Blue Swirl 已提交
4873
static void gen_lscbx(DisasContext *ctx)
4874
{
4875 4876 4877 4878
    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));
4879

A
aurel32 已提交
4880
    gen_addr_reg_index(ctx, t0);
4881
    gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
4882 4883 4884
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
A
aurel32 已提交
4885
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4886
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4887
    if (unlikely(Rc(ctx->opcode) != 0))
4888 4889
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4890 4891 4892
}

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

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

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

/* mulo - mulo. */
B
Blue Swirl 已提交
4953
static void gen_mulo(DisasContext *ctx)
4954
{
4955
    TCGLabel *l1 = gen_new_label();
4956 4957 4958 4959
    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 */
4960
    tcg_gen_movi_tl(cpu_ov, 0);
4961 4962 4963 4964 4965 4966 4967 4968 4969
    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);
4970 4971
    tcg_gen_movi_tl(cpu_ov, 1);
    tcg_gen_movi_tl(cpu_so, 1);
4972 4973 4974 4975
    gen_set_label(l1);
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free(t2);
4976
    if (unlikely(Rc(ctx->opcode) != 0))
4977
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4978 4979 4980
}

/* nabs - nabs. */
B
Blue Swirl 已提交
4981
static void gen_nabs(DisasContext *ctx)
4982
{
4983 4984
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
4985 4986 4987 4988 4989 4990
    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);
4991
    if (unlikely(Rc(ctx->opcode) != 0))
4992
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4993 4994 4995
}

/* nabso - nabso. */
B
Blue Swirl 已提交
4996
static void gen_nabso(DisasContext *ctx)
4997
{
4998 4999
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
5000 5001 5002 5003 5004 5005 5006
    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 */
5007
    tcg_gen_movi_tl(cpu_ov, 0);
5008
    if (unlikely(Rc(ctx->opcode) != 0))
5009
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
5010 5011 5012
}

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

/* rrib - rrib. */
B
Blue Swirl 已提交
5029
static void gen_rrib(DisasContext *ctx)
5030
{
5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041
    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);
5042
    if (unlikely(Rc(ctx->opcode) != 0))
5043
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5044 5045 5046
}

/* sle - sle. */
B
Blue Swirl 已提交
5047
static void gen_sle(DisasContext *ctx)
5048
{
5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059
    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);
5060
    if (unlikely(Rc(ctx->opcode) != 0))
5061
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5062 5063 5064
}

/* sleq - sleq. */
B
Blue Swirl 已提交
5065
static void gen_sleq(DisasContext *ctx)
5066
{
5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081
    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);
5082
    if (unlikely(Rc(ctx->opcode) != 0))
5083
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5084 5085 5086
}

/* sliq - sliq. */
B
Blue Swirl 已提交
5087
static void gen_sliq(DisasContext *ctx)
5088
{
5089 5090 5091 5092 5093 5094 5095 5096 5097 5098
    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);
5099
    if (unlikely(Rc(ctx->opcode) != 0))
5100
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5101 5102 5103
}

/* slliq - slliq. */
B
Blue Swirl 已提交
5104
static void gen_slliq(DisasContext *ctx)
5105
{
5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116
    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);
5117
    if (unlikely(Rc(ctx->opcode) != 0))
5118
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5119 5120 5121
}

/* sllq - sllq. */
B
Blue Swirl 已提交
5122
static void gen_sllq(DisasContext *ctx)
5123
{
5124 5125
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145
    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);
5146
    if (unlikely(Rc(ctx->opcode) != 0))
5147
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5148 5149 5150
}

/* slq - slq. */
B
Blue Swirl 已提交
5151
static void gen_slq(DisasContext *ctx)
5152
{
5153
    TCGLabel *l1 = gen_new_label();
5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168
    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);
5169
    if (unlikely(Rc(ctx->opcode) != 0))
5170
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5171 5172
}

5173
/* sraiq - sraiq. */
B
Blue Swirl 已提交
5174
static void gen_sraiq(DisasContext *ctx)
5175
{
5176
    int sh = SH(ctx->opcode);
5177
    TCGLabel *l1 = gen_new_label();
5178 5179 5180 5181 5182 5183
    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);
5184
    tcg_gen_movi_tl(cpu_ca, 0);
5185 5186
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
5187
    tcg_gen_movi_tl(cpu_ca, 1);
5188 5189 5190 5191
    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);
5192
    if (unlikely(Rc(ctx->opcode) != 0))
5193
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5194 5195 5196
}

/* sraq - sraq. */
B
Blue Swirl 已提交
5197
static void gen_sraq(DisasContext *ctx)
5198
{
5199 5200
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217
    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);
5218
    tcg_gen_movi_tl(cpu_ca, 0);
5219 5220
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
5221
    tcg_gen_movi_tl(cpu_ca, 1);
5222 5223 5224
    gen_set_label(l2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
5225
    if (unlikely(Rc(ctx->opcode) != 0))
5226
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5227 5228 5229
}

/* sre - sre. */
B
Blue Swirl 已提交
5230
static void gen_sre(DisasContext *ctx)
5231
{
5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242
    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);
5243
    if (unlikely(Rc(ctx->opcode) != 0))
5244
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5245 5246 5247
}

/* srea - srea. */
B
Blue Swirl 已提交
5248
static void gen_srea(DisasContext *ctx)
5249
{
5250 5251 5252 5253 5254 5255 5256 5257
    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);
5258
    if (unlikely(Rc(ctx->opcode) != 0))
5259
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5260 5261 5262
}

/* sreq */
B
Blue Swirl 已提交
5263
static void gen_sreq(DisasContext *ctx)
5264
{
5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279
    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);
5280
    if (unlikely(Rc(ctx->opcode) != 0))
5281
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5282 5283 5284
}

/* sriq */
B
Blue Swirl 已提交
5285
static void gen_sriq(DisasContext *ctx)
5286
{
5287 5288 5289 5290 5291 5292 5293 5294 5295 5296
    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);
5297
    if (unlikely(Rc(ctx->opcode) != 0))
5298
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5299 5300 5301
}

/* srliq */
B
Blue Swirl 已提交
5302
static void gen_srliq(DisasContext *ctx)
5303
{
5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314
    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);
5315
    if (unlikely(Rc(ctx->opcode) != 0))
5316
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5317 5318 5319
}

/* srlq */
B
Blue Swirl 已提交
5320
static void gen_srlq(DisasContext *ctx)
5321
{
5322 5323
    TCGLabel *l1 = gen_new_label();
    TCGLabel *l2 = gen_new_label();
5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344
    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);
5345
    if (unlikely(Rc(ctx->opcode) != 0))
5346
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5347 5348 5349
}

/* srq */
B
Blue Swirl 已提交
5350
static void gen_srq(DisasContext *ctx)
5351
{
5352
    TCGLabel *l1 = gen_new_label();
5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367
    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);
5368
    if (unlikely(Rc(ctx->opcode) != 0))
5369
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5370 5371 5372
}

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

5374
/* dsa  */
B
Blue Swirl 已提交
5375
static void gen_dsa(DisasContext *ctx)
5376 5377
{
    /* XXX: TODO */
A
aurel32 已提交
5378
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5379 5380 5381
}

/* esa */
B
Blue Swirl 已提交
5382
static void gen_esa(DisasContext *ctx)
5383 5384
{
    /* XXX: TODO */
A
aurel32 已提交
5385
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5386 5387 5388
}

/* mfrom */
B
Blue Swirl 已提交
5389
static void gen_mfrom(DisasContext *ctx)
5390 5391
{
#if defined(CONFIG_USER_ONLY)
5392
    GEN_PRIV;
5393
#else
5394
    CHK_SV;
5395
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5396
#endif /* defined(CONFIG_USER_ONLY) */
5397 5398 5399
}

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

5401
/* tlbld */
B
Blue Swirl 已提交
5402
static void gen_tlbld_6xx(DisasContext *ctx)
5403 5404
{
#if defined(CONFIG_USER_ONLY)
5405
    GEN_PRIV;
5406
#else
5407
    CHK_SV;
5408
    gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5409
#endif /* defined(CONFIG_USER_ONLY) */
5410 5411 5412
}

/* tlbli */
B
Blue Swirl 已提交
5413
static void gen_tlbli_6xx(DisasContext *ctx)
5414 5415
{
#if defined(CONFIG_USER_ONLY)
5416
    GEN_PRIV;
5417
#else
5418
    CHK_SV;
5419
    gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5420
#endif /* defined(CONFIG_USER_ONLY) */
5421 5422
}

5423
/* 74xx TLB management */
B
Blue Swirl 已提交
5424

5425
/* tlbld */
B
Blue Swirl 已提交
5426
static void gen_tlbld_74xx(DisasContext *ctx)
5427 5428
{
#if defined(CONFIG_USER_ONLY)
5429
    GEN_PRIV;
5430
#else
5431
    CHK_SV;
5432
    gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5433
#endif /* defined(CONFIG_USER_ONLY) */
5434 5435 5436
}

/* tlbli */
B
Blue Swirl 已提交
5437
static void gen_tlbli_74xx(DisasContext *ctx)
5438 5439
{
#if defined(CONFIG_USER_ONLY)
5440
    GEN_PRIV;
5441
#else
5442
    CHK_SV;
5443
    gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5444
#endif /* defined(CONFIG_USER_ONLY) */
5445 5446
}

5447
/* POWER instructions not in PowerPC 601 */
B
Blue Swirl 已提交
5448

5449
/* clf */
B
Blue Swirl 已提交
5450
static void gen_clf(DisasContext *ctx)
5451 5452 5453 5454 5455
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
B
Blue Swirl 已提交
5456
static void gen_cli(DisasContext *ctx)
5457 5458
{
#if defined(CONFIG_USER_ONLY)
5459
    GEN_PRIV;
5460
#else
5461 5462 5463
    /* Cache line invalidate: privileged and treated as no-op */
    CHK_SV;
#endif /* defined(CONFIG_USER_ONLY) */
5464 5465 5466
}

/* dclst */
B
Blue Swirl 已提交
5467
static void gen_dclst(DisasContext *ctx)
5468 5469 5470 5471
{
    /* Data cache line store: treated as no-op */
}

B
Blue Swirl 已提交
5472
static void gen_mfsri(DisasContext *ctx)
5473 5474
{
#if defined(CONFIG_USER_ONLY)
5475
    GEN_PRIV;
5476
#else
5477 5478 5479
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
5480 5481

    CHK_SV;
5482
    t0 = tcg_temp_new();
A
aurel32 已提交
5483
    gen_addr_reg_index(ctx, t0);
5484
    tcg_gen_extract_tl(t0, t0, 28, 4);
5485
    gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
5486
    tcg_temp_free(t0);
5487
    if (ra != 0 && ra != rd)
5488
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5489
#endif /* defined(CONFIG_USER_ONLY) */
5490 5491
}

B
Blue Swirl 已提交
5492
static void gen_rac(DisasContext *ctx)
5493 5494
{
#if defined(CONFIG_USER_ONLY)
5495
    GEN_PRIV;
5496
#else
5497
    TCGv t0;
5498 5499

    CHK_SV;
5500
    t0 = tcg_temp_new();
A
aurel32 已提交
5501
    gen_addr_reg_index(ctx, t0);
5502
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5503
    tcg_temp_free(t0);
5504
#endif /* defined(CONFIG_USER_ONLY) */
5505 5506
}

B
Blue Swirl 已提交
5507
static void gen_rfsvc(DisasContext *ctx)
5508 5509
{
#if defined(CONFIG_USER_ONLY)
5510
    GEN_PRIV;
5511
#else
5512 5513
    CHK_SV;

5514
    gen_helper_rfsvc(cpu_env);
A
aurel32 已提交
5515
    gen_sync_exception(ctx);
5516
#endif /* defined(CONFIG_USER_ONLY) */
5517 5518
}

5519
/* svc is not implemented for now */
5520 5521

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

5523
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5524
static void gen_mfapidi(DisasContext *ctx)
5525 5526
{
    /* XXX: TODO */
A
aurel32 已提交
5527
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5528 5529
}

5530
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5531
static void gen_tlbiva(DisasContext *ctx)
5532 5533
{
#if defined(CONFIG_USER_ONLY)
5534
    GEN_PRIV;
5535
#else
5536
    TCGv t0;
5537 5538

    CHK_SV;
5539
    t0 = tcg_temp_new();
A
aurel32 已提交
5540
    gen_addr_reg_index(ctx, t0);
5541
    gen_helper_tlbiva(cpu_env, cpu_gpr[rB(ctx->opcode)]);
5542
    tcg_temp_free(t0);
5543
#endif /* defined(CONFIG_USER_ONLY) */
5544 5545 5546
}

/* All 405 MAC instructions are translated here */
B
Blue Swirl 已提交
5547 5548
static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
                                        int ra, int rb, int rt, int Rc)
5549
{
5550 5551
    TCGv t0, t1;

P
pbrook 已提交
5552 5553
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5554

5555 5556 5557 5558 5559 5560 5561
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5562 5563 5564
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5565 5566 5567 5568 5569
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5570 5571 5572
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5573 5574 5575 5576 5577 5578 5579
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5580 5581 5582 5583
        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);
5584 5585 5586 5587 5588
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5589 5590 5591 5592
        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);
5593 5594 5595 5596 5597 5598 5599
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5600 5601
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5602 5603 5604 5605 5606
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5607 5608
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5609 5610 5611
        break;
    }
    if (opc2 & 0x04) {
5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623
        /* (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 */
5624
            TCGLabel *l1 = gen_new_label();
5625 5626 5627

            if (opc3 & 0x10) {
                /* Start with XER OV disabled, the most likely case */
5628
                tcg_gen_movi_tl(cpu_ov, 0);
5629 5630 5631 5632 5633 5634 5635
            }
            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 已提交
5636
                if (opc3 & 0x02) {
5637 5638 5639 5640 5641 5642 5643
                    /* 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 已提交
5644
                if (opc3 & 0x02) {
5645 5646 5647 5648 5649 5650
                    /* Saturate */
                    tcg_gen_movi_tl(t0, UINT32_MAX);
                }
            }
            if (opc3 & 0x10) {
                /* Check overflow */
5651 5652
                tcg_gen_movi_tl(cpu_ov, 1);
                tcg_gen_movi_tl(cpu_so, 1);
5653 5654 5655 5656 5657 5658
            }
            gen_set_label(l1);
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
        }
    } else {
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5659
    }
5660 5661
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5662 5663
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5664
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5665 5666 5667
    }
}

5668
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
B
Blue Swirl 已提交
5669
static void glue(gen_, name)(DisasContext *ctx)                               \
5670 5671 5672 5673 5674 5675
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5676
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5677
/* macchwo   - macchwo.   */
5678
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5679
/* macchws   - macchws.   */
5680
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5681
/* macchwso  - macchwso.  */
5682
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5683
/* macchwsu  - macchwsu.  */
5684
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5685
/* macchwsuo - macchwsuo. */
5686
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5687
/* macchwu   - macchwu.   */
5688
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5689
/* macchwuo  - macchwuo.  */
5690
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5691
/* machhw    - machhw.    */
5692
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5693
/* machhwo   - machhwo.   */
5694
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5695
/* machhws   - machhws.   */
5696
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5697
/* machhwso  - machhwso.  */
5698
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5699
/* machhwsu  - machhwsu.  */
5700
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5701
/* machhwsuo - machhwsuo. */
5702
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5703
/* machhwu   - machhwu.   */
5704
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5705
/* machhwuo  - machhwuo.  */
5706
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5707
/* maclhw    - maclhw.    */
5708
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5709
/* maclhwo   - maclhwo.   */
5710
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5711
/* maclhws   - maclhws.   */
5712
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5713
/* maclhwso  - maclhwso.  */
5714
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5715
/* maclhwu   - maclhwu.   */
5716
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5717
/* maclhwuo  - maclhwuo.  */
5718
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5719
/* maclhwsu  - maclhwsu.  */
5720
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5721
/* maclhwsuo - maclhwsuo. */
5722
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5723
/* nmacchw   - nmacchw.   */
5724
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5725
/* nmacchwo  - nmacchwo.  */
5726
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5727
/* nmacchws  - nmacchws.  */
5728
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5729
/* nmacchwso - nmacchwso. */
5730
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5731
/* nmachhw   - nmachhw.   */
5732
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5733
/* nmachhwo  - nmachhwo.  */
5734
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5735
/* nmachhws  - nmachhws.  */
5736
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5737
/* nmachhwso - nmachhwso. */
5738
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5739
/* nmaclhw   - nmaclhw.   */
5740
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5741
/* nmaclhwo  - nmaclhwo.  */
5742
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5743
/* nmaclhws  - nmaclhws.  */
5744
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5745
/* nmaclhwso - nmaclhwso. */
5746
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5747 5748

/* mulchw  - mulchw.  */
5749
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5750
/* mulchwu - mulchwu. */
5751
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5752
/* mulhhw  - mulhhw.  */
5753
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5754
/* mulhhwu - mulhhwu. */
5755
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5756
/* mullhw  - mullhw.  */
5757
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5758
/* mullhwu - mullhwu. */
5759
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5760 5761

/* mfdcr */
B
Blue Swirl 已提交
5762
static void gen_mfdcr(DisasContext *ctx)
5763 5764
{
#if defined(CONFIG_USER_ONLY)
5765
    GEN_PRIV;
5766
#else
5767
    TCGv dcrn;
5768 5769

    CHK_SV;
5770
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5771
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
5772
    tcg_temp_free(dcrn);
5773
#endif /* defined(CONFIG_USER_ONLY) */
5774 5775 5776
}

/* mtdcr */
B
Blue Swirl 已提交
5777
static void gen_mtdcr(DisasContext *ctx)
5778 5779
{
#if defined(CONFIG_USER_ONLY)
5780
    GEN_PRIV;
5781
#else
5782
    TCGv dcrn;
5783 5784

    CHK_SV;
5785
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5786
    gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
5787
    tcg_temp_free(dcrn);
5788
#endif /* defined(CONFIG_USER_ONLY) */
5789 5790 5791
}

/* mfdcrx */
5792
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5793
static void gen_mfdcrx(DisasContext *ctx)
5794 5795
{
#if defined(CONFIG_USER_ONLY)
5796
    GEN_PRIV;
5797
#else
5798
    CHK_SV;
5799 5800
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5801
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5802
#endif /* defined(CONFIG_USER_ONLY) */
5803 5804 5805
}

/* mtdcrx */
5806
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5807
static void gen_mtdcrx(DisasContext *ctx)
5808 5809
{
#if defined(CONFIG_USER_ONLY)
5810
    GEN_PRIV;
5811
#else
5812
    CHK_SV;
5813 5814
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
                         cpu_gpr[rS(ctx->opcode)]);
5815
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5816
#endif /* defined(CONFIG_USER_ONLY) */
5817 5818
}

5819
/* mfdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5820
static void gen_mfdcrux(DisasContext *ctx)
5821
{
5822 5823
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
                        cpu_gpr[rA(ctx->opcode)]);
5824 5825 5826 5827
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
B
Blue Swirl 已提交
5828
static void gen_mtdcrux(DisasContext *ctx)
5829
{
5830
    gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
5831
                         cpu_gpr[rS(ctx->opcode)]);
5832 5833 5834
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5835
/* dccci */
B
Blue Swirl 已提交
5836
static void gen_dccci(DisasContext *ctx)
5837
{
5838
    CHK_SV;
5839 5840 5841 5842
    /* interpreted as no-op */
}

/* dcread */
B
Blue Swirl 已提交
5843
static void gen_dcread(DisasContext *ctx)
5844 5845
{
#if defined(CONFIG_USER_ONLY)
5846
    GEN_PRIV;
5847
#else
A
aurel32 已提交
5848
    TCGv EA, val;
5849 5850

    CHK_SV;
A
aurel32 已提交
5851
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5852
    EA = tcg_temp_new();
A
aurel32 已提交
5853
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5854
    val = tcg_temp_new();
A
aurel32 已提交
5855
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5856 5857 5858
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5859
#endif /* defined(CONFIG_USER_ONLY) */
5860 5861 5862
}

/* icbt */
B
Blue Swirl 已提交
5863
static void gen_icbt_40x(DisasContext *ctx)
5864 5865 5866 5867 5868 5869 5870 5871
{
    /* 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 已提交
5872
static void gen_iccci(DisasContext *ctx)
5873
{
5874
    CHK_SV;
5875 5876 5877 5878
    /* interpreted as no-op */
}

/* icread */
B
Blue Swirl 已提交
5879
static void gen_icread(DisasContext *ctx)
5880
{
5881
    CHK_SV;
5882 5883 5884
    /* interpreted as no-op */
}

5885
/* rfci (supervisor only) */
B
Blue Swirl 已提交
5886
static void gen_rfci_40x(DisasContext *ctx)
5887 5888
{
#if defined(CONFIG_USER_ONLY)
5889
    GEN_PRIV;
5890
#else
5891
    CHK_SV;
5892
    /* Restore CPU state */
5893
    gen_helper_40x_rfci(cpu_env);
A
aurel32 已提交
5894
    gen_sync_exception(ctx);
5895
#endif /* defined(CONFIG_USER_ONLY) */
5896 5897
}

B
Blue Swirl 已提交
5898
static void gen_rfci(DisasContext *ctx)
5899 5900
{
#if defined(CONFIG_USER_ONLY)
5901
    GEN_PRIV;
5902
#else
5903
    CHK_SV;
5904
    /* Restore CPU state */
5905
    gen_helper_rfci(cpu_env);
A
aurel32 已提交
5906
    gen_sync_exception(ctx);
5907
#endif /* defined(CONFIG_USER_ONLY) */
5908 5909 5910
}

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

5912
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5913
static void gen_rfdi(DisasContext *ctx)
5914 5915
{
#if defined(CONFIG_USER_ONLY)
5916
    GEN_PRIV;
5917
#else
5918
    CHK_SV;
5919
    /* Restore CPU state */
5920
    gen_helper_rfdi(cpu_env);
A
aurel32 已提交
5921
    gen_sync_exception(ctx);
5922
#endif /* defined(CONFIG_USER_ONLY) */
5923 5924
}

5925
/* XXX: not implemented on 440 ? */
B
Blue Swirl 已提交
5926
static void gen_rfmci(DisasContext *ctx)
5927 5928
{
#if defined(CONFIG_USER_ONLY)
5929
    GEN_PRIV;
5930
#else
5931
    CHK_SV;
5932
    /* Restore CPU state */
5933
    gen_helper_rfmci(cpu_env);
A
aurel32 已提交
5934
    gen_sync_exception(ctx);
5935
#endif /* defined(CONFIG_USER_ONLY) */
5936
}
5937

5938
/* TLB management - PowerPC 405 implementation */
B
Blue Swirl 已提交
5939

5940
/* tlbre */
B
Blue Swirl 已提交
5941
static void gen_tlbre_40x(DisasContext *ctx)
5942 5943
{
#if defined(CONFIG_USER_ONLY)
5944
    GEN_PRIV;
5945
#else
5946
    CHK_SV;
5947 5948
    switch (rB(ctx->opcode)) {
    case 0:
5949 5950
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
5951 5952
        break;
    case 1:
5953 5954
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                cpu_gpr[rA(ctx->opcode)]);
5955 5956
        break;
    default:
A
aurel32 已提交
5957
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5958
        break;
5959
    }
5960
#endif /* defined(CONFIG_USER_ONLY) */
5961 5962
}

5963
/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
5964
static void gen_tlbsx_40x(DisasContext *ctx)
5965 5966
{
#if defined(CONFIG_USER_ONLY)
5967
    GEN_PRIV;
5968
#else
5969
    TCGv t0;
5970 5971

    CHK_SV;
5972
    t0 = tcg_temp_new();
A
aurel32 已提交
5973
    gen_addr_reg_index(ctx, t0);
5974
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
5975 5976
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
5977
        TCGLabel *l1 = gen_new_label();
5978
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
5979 5980 5981 5982
        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);
    }
5983
#endif /* defined(CONFIG_USER_ONLY) */
B
bellard 已提交
5984 5985
}

5986
/* tlbwe */
B
Blue Swirl 已提交
5987
static void gen_tlbwe_40x(DisasContext *ctx)
B
bellard 已提交
5988
{
5989
#if defined(CONFIG_USER_ONLY)
5990
    GEN_PRIV;
5991
#else
5992 5993
    CHK_SV;

5994 5995
    switch (rB(ctx->opcode)) {
    case 0:
5996 5997
        gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
5998 5999
        break;
    case 1:
6000 6001
        gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
                                cpu_gpr[rS(ctx->opcode)]);
6002 6003
        break;
    default:
A
aurel32 已提交
6004
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6005
        break;
6006
    }
6007
#endif /* defined(CONFIG_USER_ONLY) */
6008 6009
}

6010
/* TLB management - PowerPC 440 implementation */
B
Blue Swirl 已提交
6011

6012
/* tlbre */
B
Blue Swirl 已提交
6013
static void gen_tlbre_440(DisasContext *ctx)
6014 6015
{
#if defined(CONFIG_USER_ONLY)
6016
    GEN_PRIV;
6017
#else
6018 6019
    CHK_SV;

6020 6021 6022 6023
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6024 6025
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6026 6027
            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
                                 t0, cpu_gpr[rA(ctx->opcode)]);
6028 6029
            tcg_temp_free_i32(t0);
        }
6030 6031
        break;
    default:
A
aurel32 已提交
6032
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6033 6034
        break;
    }
6035
#endif /* defined(CONFIG_USER_ONLY) */
6036 6037 6038
}

/* tlbsx - tlbsx. */
B
Blue Swirl 已提交
6039
static void gen_tlbsx_440(DisasContext *ctx)
6040 6041
{
#if defined(CONFIG_USER_ONLY)
6042
    GEN_PRIV;
6043
#else
6044
    TCGv t0;
6045 6046

    CHK_SV;
6047
    t0 = tcg_temp_new();
A
aurel32 已提交
6048
    gen_addr_reg_index(ctx, t0);
6049
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
6050 6051
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
6052
        TCGLabel *l1 = gen_new_label();
6053
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
6054 6055 6056 6057
        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);
    }
6058
#endif /* defined(CONFIG_USER_ONLY) */
6059 6060 6061
}

/* tlbwe */
B
Blue Swirl 已提交
6062
static void gen_tlbwe_440(DisasContext *ctx)
6063 6064
{
#if defined(CONFIG_USER_ONLY)
6065
    GEN_PRIV;
6066
#else
6067
    CHK_SV;
6068 6069 6070 6071
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
6072 6073
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
6074 6075
            gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
                                 cpu_gpr[rS(ctx->opcode)]);
6076 6077
            tcg_temp_free_i32(t0);
        }
6078 6079
        break;
    default:
A
aurel32 已提交
6080
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6081 6082
        break;
    }
6083
#endif /* defined(CONFIG_USER_ONLY) */
6084 6085
}

A
Alexander Graf 已提交
6086 6087 6088 6089 6090
/* TLB management - PowerPC BookE 2.06 implementation */

/* tlbre */
static void gen_tlbre_booke206(DisasContext *ctx)
{
6091 6092
 #if defined(CONFIG_USER_ONLY)
    GEN_PRIV;
A
Alexander Graf 已提交
6093
#else
6094
   CHK_SV;
6095
    gen_helper_booke206_tlbre(cpu_env);
6096
#endif /* defined(CONFIG_USER_ONLY) */
A
Alexander Graf 已提交
6097 6098 6099 6100 6101 6102
}

/* tlbsx - tlbsx. */
static void gen_tlbsx_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
6103
    GEN_PRIV;
A
Alexander Graf 已提交
6104 6105 6106
#else
    TCGv t0;

6107
    CHK_SV;
A
Alexander Graf 已提交
6108 6109 6110 6111 6112 6113 6114 6115
    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)]);
6116
    gen_helper_booke206_tlbsx(cpu_env, t0);
6117
    tcg_temp_free(t0);
6118
#endif /* defined(CONFIG_USER_ONLY) */
A
Alexander Graf 已提交
6119 6120 6121 6122 6123 6124
}

/* tlbwe */
static void gen_tlbwe_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
6125
    GEN_PRIV;
A
Alexander Graf 已提交
6126
#else
6127
    CHK_SV;
6128
    gen_helper_booke206_tlbwe(cpu_env);
6129
#endif /* defined(CONFIG_USER_ONLY) */
A
Alexander Graf 已提交
6130 6131 6132 6133 6134
}

static void gen_tlbivax_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
6135
    GEN_PRIV;
A
Alexander Graf 已提交
6136 6137 6138
#else
    TCGv t0;

6139
    CHK_SV;
A
Alexander Graf 已提交
6140 6141
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
6142
    gen_helper_booke206_tlbivax(cpu_env, t0);
6143
    tcg_temp_free(t0);
6144
#endif /* defined(CONFIG_USER_ONLY) */
A
Alexander Graf 已提交
6145 6146
}

A
Alexander Graf 已提交
6147 6148 6149
static void gen_tlbilx_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
6150
    GEN_PRIV;
A
Alexander Graf 已提交
6151 6152 6153
#else
    TCGv t0;

6154
    CHK_SV;
A
Alexander Graf 已提交
6155 6156 6157 6158 6159
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);

    switch((ctx->opcode >> 21) & 0x3) {
    case 0:
6160
        gen_helper_booke206_tlbilx0(cpu_env, t0);
A
Alexander Graf 已提交
6161 6162
        break;
    case 1:
6163
        gen_helper_booke206_tlbilx1(cpu_env, t0);
A
Alexander Graf 已提交
6164 6165
        break;
    case 3:
6166
        gen_helper_booke206_tlbilx3(cpu_env, t0);
A
Alexander Graf 已提交
6167 6168 6169 6170 6171 6172 6173
        break;
    default:
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
        break;
    }

    tcg_temp_free(t0);
6174
#endif /* defined(CONFIG_USER_ONLY) */
A
Alexander Graf 已提交
6175 6176
}

A
Alexander Graf 已提交
6177

6178
/* wrtee */
B
Blue Swirl 已提交
6179
static void gen_wrtee(DisasContext *ctx)
6180 6181
{
#if defined(CONFIG_USER_ONLY)
6182
    GEN_PRIV;
6183
#else
6184
    TCGv t0;
6185 6186

    CHK_SV;
6187 6188 6189 6190 6191
    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 已提交
6192 6193 6194
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
6195
    gen_stop_exception(ctx);
6196
#endif /* defined(CONFIG_USER_ONLY) */
6197 6198 6199
}

/* wrteei */
B
Blue Swirl 已提交
6200
static void gen_wrteei(DisasContext *ctx)
6201 6202
{
#if defined(CONFIG_USER_ONLY)
6203
    GEN_PRIV;
6204
#else
6205
    CHK_SV;
6206
    if (ctx->opcode & 0x00008000) {
6207 6208
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6209
        gen_stop_exception(ctx);
6210
    } else {
A
aurel32 已提交
6211
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6212
    }
6213
#endif /* defined(CONFIG_USER_ONLY) */
6214 6215
}

J
j_mayer 已提交
6216
/* PowerPC 440 specific instructions */
B
Blue Swirl 已提交
6217

6218
/* dlmzb */
B
Blue Swirl 已提交
6219
static void gen_dlmzb(DisasContext *ctx)
6220
{
6221
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6222 6223
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
                     cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
6224
    tcg_temp_free_i32(t0);
6225 6226 6227
}

/* mbar replaces eieio on 440 */
B
Blue Swirl 已提交
6228
static void gen_mbar(DisasContext *ctx)
6229 6230 6231 6232 6233
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
A
Alexander Graf 已提交
6234
static void gen_msync_4xx(DisasContext *ctx)
6235 6236 6237 6238 6239
{
    /* interpreted as no-op */
}

/* icbt */
B
Blue Swirl 已提交
6240
static void gen_icbt_440(DisasContext *ctx)
6241 6242 6243 6244 6245
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6246 6247
}

A
Alexander Graf 已提交
6248 6249 6250 6251 6252
/* Embedded.Processor Control */

static void gen_msgclr(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
6253
    GEN_PRIV;
A
Alexander Graf 已提交
6254
#else
6255
    CHK_HV;
6256 6257 6258 6259 6260 6261
    /* 64-bit server processors compliant with arch 2.x */
    if (ctx->insns_flags & PPC_SEGMENT_64B) {
        gen_helper_book3s_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
    } else {
        gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
    }
6262
#endif /* defined(CONFIG_USER_ONLY) */
A
Alexander Graf 已提交
6263 6264
}

A
Alexander Graf 已提交
6265 6266 6267
static void gen_msgsnd(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
6268
    GEN_PRIV;
A
Alexander Graf 已提交
6269
#else
6270
    CHK_HV;
6271 6272 6273 6274 6275 6276
    /* 64-bit server processors compliant with arch 2.x */
    if (ctx->insns_flags & PPC_SEGMENT_64B) {
        gen_helper_book3s_msgsnd(cpu_gpr[rB(ctx->opcode)]);
    } else {
        gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
    }
6277
#endif /* defined(CONFIG_USER_ONLY) */
A
Alexander Graf 已提交
6278 6279
}

6280 6281 6282 6283 6284 6285 6286 6287 6288
static void gen_msgsync(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
    GEN_PRIV;
#else
    CHK_HV;
#endif /* defined(CONFIG_USER_ONLY) */
    /* interpreted as no-op */
}
A
aurel32 已提交
6289

6290 6291 6292 6293 6294 6295 6296 6297 6298
#if defined(TARGET_PPC64)
static void gen_maddld(DisasContext *ctx)
{
    TCGv_i64 t1 = tcg_temp_new_i64();

    tcg_gen_mul_i64(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_add_i64(cpu_gpr[rD(ctx->opcode)], t1, cpu_gpr[rC(ctx->opcode)]);
    tcg_temp_free_i64(t1);
}
6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321

/* maddhd maddhdu */
static void gen_maddhd_maddhdu(DisasContext *ctx)
{
    TCGv_i64 lo = tcg_temp_new_i64();
    TCGv_i64 hi = tcg_temp_new_i64();
    TCGv_i64 t1 = tcg_temp_new_i64();

    if (Rc(ctx->opcode)) {
        tcg_gen_mulu2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)],
                          cpu_gpr[rB(ctx->opcode)]);
        tcg_gen_movi_i64(t1, 0);
    } else {
        tcg_gen_muls2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)],
                          cpu_gpr[rB(ctx->opcode)]);
        tcg_gen_sari_i64(t1, cpu_gpr[rC(ctx->opcode)], 63);
    }
    tcg_gen_add2_i64(t1, cpu_gpr[rD(ctx->opcode)], lo, hi,
                     cpu_gpr[rC(ctx->opcode)], t1);
    tcg_temp_free_i64(lo);
    tcg_temp_free_i64(hi);
    tcg_temp_free_i64(t1);
}
6322 6323
#endif /* defined(TARGET_PPC64) */

T
Tom Musta 已提交
6324 6325 6326 6327 6328 6329 6330 6331 6332
static void gen_tbegin(DisasContext *ctx)
{
    if (unlikely(!ctx->tm_enabled)) {
        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
        return;
    }
    gen_helper_tbegin(cpu_env);
}

T
Tom Musta 已提交
6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355
#define GEN_TM_NOOP(name)                                      \
static inline void gen_##name(DisasContext *ctx)               \
{                                                              \
    if (unlikely(!ctx->tm_enabled)) {                          \
        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);   \
        return;                                                \
    }                                                          \
    /* Because tbegin always fails in QEMU, these user         \
     * space instructions all have a simple implementation:    \
     *                                                         \
     *     CR[0] = 0b0 || MSR[TS] || 0b0                       \
     *           = 0b0 || 0b00    || 0b0                       \
     */                                                        \
    tcg_gen_movi_i32(cpu_crf[0], 0);                           \
}

GEN_TM_NOOP(tend);
GEN_TM_NOOP(tabort);
GEN_TM_NOOP(tabortwc);
GEN_TM_NOOP(tabortwci);
GEN_TM_NOOP(tabortdc);
GEN_TM_NOOP(tabortdci);
GEN_TM_NOOP(tsr);
6356 6357 6358 6359
static inline void gen_cp_abort(DisasContext *ctx)
{
    // Do Nothing
}
T
Tom Musta 已提交
6360

6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373
#define GEN_CP_PASTE_NOOP(name)                           \
static inline void gen_##name(DisasContext *ctx)          \
{                                                         \
    /* Generate invalid exception until                   \
     * we have an implementation of the copy              \
     * paste facility                                     \
     */                                                   \
    gen_invalid(ctx);                                     \
}

GEN_CP_PASTE_NOOP(copy)
GEN_CP_PASTE_NOOP(paste)

T
Tom Musta 已提交
6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388
static void gen_tcheck(DisasContext *ctx)
{
    if (unlikely(!ctx->tm_enabled)) {
        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
        return;
    }
    /* Because tbegin always fails, the tcheck implementation
     * is simple:
     *
     * CR[CRF] = TDOOMED || MSR[TS] || 0b0
     *         = 0b1 || 0b00 || 0b0
     */
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0x8);
}

6389 6390 6391 6392
#if defined(CONFIG_USER_ONLY)
#define GEN_TM_PRIV_NOOP(name)                                 \
static inline void gen_##name(DisasContext *ctx)               \
{                                                              \
6393
    gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);           \
6394 6395 6396 6397 6398 6399 6400
}

#else

#define GEN_TM_PRIV_NOOP(name)                                 \
static inline void gen_##name(DisasContext *ctx)               \
{                                                              \
6401
    CHK_SV;                                                    \
6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419
    if (unlikely(!ctx->tm_enabled)) {                          \
        gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);   \
        return;                                                \
    }                                                          \
    /* Because tbegin always fails, the implementation is      \
     * simple:                                                 \
     *                                                         \
     *   CR[0] = 0b0 || MSR[TS] || 0b0                         \
     *         = 0b0 || 0b00 | 0b0                             \
     */                                                        \
    tcg_gen_movi_i32(cpu_crf[0], 0);                           \
}

#endif

GEN_TM_PRIV_NOOP(treclaim);
GEN_TM_PRIV_NOOP(trechkpt);

6420 6421 6422 6423 6424 6425 6426 6427 6428 6429
#include "translate/fp-impl.inc.c"

#include "translate/vmx-impl.inc.c"

#include "translate/vsx-impl.inc.c"

#include "translate/dfp-impl.inc.c"

#include "translate/spe-impl.inc.c"

6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452
/* Handles lfdp, lxsd, lxssp */
static void gen_dform39(DisasContext *ctx)
{
    switch (ctx->opcode & 0x3) {
    case 0: /* lfdp */
        if (ctx->insns_flags2 & PPC2_ISA205) {
            return gen_lfdp(ctx);
        }
        break;
    case 2: /* lxsd */
        if (ctx->insns_flags2 & PPC2_ISA300) {
            return gen_lxsd(ctx);
        }
        break;
    case 3: /* lxssp */
        if (ctx->insns_flags2 & PPC2_ISA300) {
            return gen_lxssp(ctx);
        }
        break;
    }
    return gen_invalid(ctx);
}

6453
/* handles stfdp, lxv, stxsd, stxssp lxvx */
6454 6455 6456 6457 6458
static void gen_dform3D(DisasContext *ctx)
{
    if ((ctx->opcode & 3) == 1) { /* DQ-FORM */
        switch (ctx->opcode & 0x7) {
        case 1: /* lxv */
6459 6460 6461
            if (ctx->insns_flags2 & PPC2_ISA300) {
                return gen_lxv(ctx);
            }
6462 6463
            break;
        case 5: /* stxv */
6464 6465 6466
            if (ctx->insns_flags2 & PPC2_ISA300) {
                return gen_stxv(ctx);
            }
6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490
            break;
        }
    } else { /* DS-FORM */
        switch (ctx->opcode & 0x3) {
        case 0: /* stfdp */
            if (ctx->insns_flags2 & PPC2_ISA205) {
                return gen_stfdp(ctx);
            }
            break;
        case 2: /* stxsd */
            if (ctx->insns_flags2 & PPC2_ISA300) {
                return gen_stxsd(ctx);
            }
            break;
        case 3: /* stxssp */
            if (ctx->insns_flags2 & PPC2_ISA300) {
                return gen_stxssp(ctx);
            }
            break;
        }
    }
    return gen_invalid(ctx);
}

A
Anthony Liguori 已提交
6491
static opcode_t opcodes[] = {
6492 6493 6494
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),
6495
GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400001, PPC_INTEGER),
6496
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
6497 6498 6499
#if defined(TARGET_PPC64)
GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300),
#endif
6500
GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
6501
GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x00400001, PPC_NONE, PPC2_ISA300),
6502 6503 6504 6505 6506
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),
6507
GEN_HANDLER_E(addpcis, 0x13, 0x2, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300),
6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521
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),
6522
GEN_HANDLER_E(cnttzw, 0x1F, 0x1A, 0x10, 0x00000000, PPC_NONE, PPC2_ISA300),
6523
GEN_HANDLER_E(copy, 0x1F, 0x06, 0x18, 0x03C00001, PPC_NONE, PPC2_ISA300),
6524
GEN_HANDLER_E(cp_abort, 0x1F, 0x06, 0x1A, 0x03FFF801, PPC_NONE, PPC2_ISA300),
6525
GEN_HANDLER_E(paste, 0x1F, 0x06, 0x1C, 0x03C00000, PPC_NONE, PPC2_ISA300),
6526 6527 6528 6529 6530 6531
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),
T
Tom Musta 已提交
6532
GEN_HANDLER(popcntb, 0x1F, 0x1A, 0x03, 0x0000F801, PPC_POPCNTB),
6533
GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
6534
GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
6535
#if defined(TARGET_PPC64)
6536
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
6537
GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
6538
GEN_HANDLER_E(cnttzd, 0x1F, 0x1A, 0x11, 0x00000000, PPC_NONE, PPC2_ISA300),
6539
GEN_HANDLER_E(darn, 0x1F, 0x13, 0x17, 0x001CF801, PPC_NONE, PPC2_ISA300),
6540
GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
6541
GEN_HANDLER_E(bpermd, 0x1F, 0x1C, 0x07, 0x00000001, PPC_NONE, PPC2_PERM_ISA206),
6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555
#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),
6556 6557 6558 6559
GEN_HANDLER2_E(extswsli0, "extswsli", 0x1F, 0x1A, 0x1B, 0x00000000,
               PPC_NONE, PPC2_ISA300),
GEN_HANDLER2_E(extswsli1, "extswsli", 0x1F, 0x1B, 0x1B, 0x00000000,
               PPC_NONE, PPC2_ISA300),
6560 6561 6562 6563 6564 6565
#endif
#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
6566 6567
/* handles lfdp, lxsd, lxssp */
GEN_HANDLER_E(dform39, 0x39, 0xFF, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA205),
6568
/* handles stfdp, lxv, stxsd, stxssp, stxv */
6569
GEN_HANDLER_E(dform3D, 0x3D, 0xFF, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA205),
6570 6571 6572 6573 6574 6575
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),
6576
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x01FFF801, PPC_MEM_EIEIO),
6577
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
6578 6579
GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
6580
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
6581
GEN_HANDLER_E(lwat, 0x1F, 0x06, 0x12, 0x00000001, PPC_NONE, PPC2_ISA300),
6582
GEN_HANDLER_E(stwat, 0x1F, 0x06, 0x16, 0x00000001, PPC_NONE, PPC2_ISA300),
6583 6584
GEN_HANDLER_E(stbcx_, 0x1F, 0x16, 0x15, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
GEN_HANDLER_E(sthcx_, 0x1F, 0x16, 0x16, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
6585 6586
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
6587
GEN_HANDLER_E(ldat, 0x1F, 0x06, 0x13, 0x00000001, PPC_NONE, PPC2_ISA300),
6588
GEN_HANDLER_E(stdat, 0x1F, 0x06, 0x17, 0x00000001, PPC_NONE, PPC2_ISA300),
6589
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
6590
GEN_HANDLER_E(lqarx, 0x1F, 0x14, 0x08, 0, PPC_NONE, PPC2_LSQ_ISA207),
6591
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
6592
GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207),
6593 6594 6595
#endif
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
6596
GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039FF801, PPC_NONE, PPC2_ISA300),
6597 6598 6599 6600
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),
6601
GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0x0000E000, PPC_NONE, PPC2_BCTAR_ISA207),
6602 6603 6604 6605
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),
6606
GEN_HANDLER_E(stop, 0x13, 0x12, 0x0b, 0x03FFF801, PPC_NONE, PPC2_ISA300),
6607 6608 6609 6610
GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627
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),
6628
GEN_HANDLER_E(setb, 0x1F, 0x00, 0x04, 0x0003F801, PPC_NONE, PPC2_ISA300),
6629
GEN_HANDLER_E(mcrxrx, 0x1F, 0x00, 0x12, 0x007FF801, PPC_NONE, PPC2_ISA300),
6630
#endif
B
Benjamin Herrenschmidt 已提交
6631
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001EF801, PPC_MISC),
6632
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000000, PPC_MISC),
6633 6634 6635
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),
6636 6637
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE),
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
A
Alexander Graf 已提交
6638
GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
A
Alexander Graf 已提交
6639
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
6640
GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
6641
GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x01800001, PPC_ALTIVEC),
6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655
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),
6656 6657 6658
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),
6659
GEN_HANDLER2(slbfee_, "slbfee.", 0x1F, 0x13, 0x1E, 0x001F0000, PPC_SEGMENT_64B),
6660 6661
#endif
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
6662 6663 6664 6665
/* XXX Those instructions will need to be handled differently for
 * different ISA versions */
GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x001F0001, PPC_MEM_TLBIE),
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x001F0001, PPC_MEM_TLBIE),
6666 6667
GEN_HANDLER_E(tlbiel, 0x1F, 0x12, 0x08, 0x00100001, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(tlbie, 0x1F, 0x12, 0x09, 0x00100001, PPC_NONE, PPC2_ISA300),
6668 6669
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
#if defined(TARGET_PPC64)
B
Benjamin Herrenschmidt 已提交
6670
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x031FFC01, PPC_SLBI),
6671
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
6672
GEN_HANDLER_E(slbieg, 0x1F, 0x12, 0x0E, 0x001F0001, PPC_NONE, PPC2_ISA300),
6673
GEN_HANDLER_E(slbsync, 0x1F, 0x12, 0x0A, 0x03FFF801, PPC_NONE, PPC2_ISA300),
6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745
#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 已提交
6746
GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
6747 6748 6749 6750 6751 6752 6753 6754
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 已提交
6755 6756 6757 6758 6759 6760 6761 6762
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 已提交
6763 6764
GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
               PPC_NONE, PPC2_BOOKE206),
A
Alexander Graf 已提交
6765 6766
GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
A
Alexander Graf 已提交
6767 6768
GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
               PPC_NONE, PPC2_PRCNTL),
6769 6770
GEN_HANDLER2_E(msgsync, "msgsync", 0x1F, 0x16, 0x1B, 0x00000000,
               PPC_NONE, PPC2_PRCNTL),
6771
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
6772
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
6773
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
A
Alexander Graf 已提交
6774 6775
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
              PPC_BOOKE, PPC2_BOOKE206),
A
Alexander Graf 已提交
6776
GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
A
Alexander Graf 已提交
6777 6778
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
               PPC_BOOKE, PPC2_BOOKE206),
6779 6780
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x06, 0x08, 0x03E00001,
               PPC_440_SPEC),
6781 6782 6783 6784 6785
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(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
6786
#if defined(TARGET_PPC64)
6787 6788
GEN_HANDLER_E(maddhd_maddhdu, 0x04, 0x18, 0xFF, 0x00000000, PPC_NONE,
              PPC2_ISA300),
6789 6790
GEN_HANDLER_E(maddld, 0x04, 0x19, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300),
#endif
6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816

#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),
6817 6818
GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6819 6820
GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
6821 6822
GEN_HANDLER_E(modsw, 0x1F, 0x0B, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(moduw, 0x1F, 0x0B, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300),
6823 6824 6825 6826 6827 6828 6829 6830 6831 6832

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

6833 6834
GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
6835 6836
GEN_HANDLER_E(divde, 0x1F, 0x09, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
GEN_HANDLER_E(divdeo, 0x1F, 0x09, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6837 6838
GEN_HANDLER_E(modsd, 0x1F, 0x09, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(modud, 0x1F, 0x09, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300),
6839

6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909
#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_LD
#undef GEN_LDU
#undef GEN_LDUX
6910
#undef GEN_LDX_E
6911 6912 6913 6914 6915 6916 6917
#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),
6918
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk)                   \
6919
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932
#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)
6933 6934
GEN_LDUX(ld, ld64_i64, 0x15, 0x01, PPC_64B)
GEN_LDX(ld, ld64_i64, 0x15, 0x00, PPC_64B)
6935
GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE)
6936 6937

/* HV/P7 and later only */
6938
GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST)
6939 6940 6941
GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x18, PPC_CILDST)
GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
6942 6943 6944 6945 6946 6947 6948
#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
6949
#undef GEN_STX_E
6950 6951 6952 6953 6954 6955 6956
#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),
6957
#define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk)                   \
6958
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
6959 6960 6961 6962 6963 6964 6965 6966 6967 6968
#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)
6969 6970
GEN_STUX(std, st64_i64, 0x15, 0x05, PPC_64B)
GEN_STX(std, st64_i64, 0x15, 0x04, PPC_64B)
6971
GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE)
6972
GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST)
6973 6974 6975
GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037
#endif
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)

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

T
Tom Musta 已提交
7038 7039
GEN_HANDLER2_E(tbegin, "tbegin", 0x1F, 0x0E, 0x14, 0x01DFF800, \
               PPC_NONE, PPC2_TM),
T
Tom Musta 已提交
7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053
GEN_HANDLER2_E(tend,   "tend",   0x1F, 0x0E, 0x15, 0x01FFF800, \
               PPC_NONE, PPC2_TM),
GEN_HANDLER2_E(tabort, "tabort", 0x1F, 0x0E, 0x1C, 0x03E0F800, \
               PPC_NONE, PPC2_TM),
GEN_HANDLER2_E(tabortwc, "tabortwc", 0x1F, 0x0E, 0x18, 0x00000000, \
               PPC_NONE, PPC2_TM),
GEN_HANDLER2_E(tabortwci, "tabortwci", 0x1F, 0x0E, 0x1A, 0x00000000, \
               PPC_NONE, PPC2_TM),
GEN_HANDLER2_E(tabortdc, "tabortdc", 0x1F, 0x0E, 0x19, 0x00000000, \
               PPC_NONE, PPC2_TM),
GEN_HANDLER2_E(tabortdci, "tabortdci", 0x1F, 0x0E, 0x1B, 0x00000000, \
               PPC_NONE, PPC2_TM),
GEN_HANDLER2_E(tsr, "tsr", 0x1F, 0x0E, 0x17, 0x03DFF800, \
               PPC_NONE, PPC2_TM),
T
Tom Musta 已提交
7054 7055
GEN_HANDLER2_E(tcheck, "tcheck", 0x1F, 0x0E, 0x16, 0x007FF800, \
               PPC_NONE, PPC2_TM),
7056 7057 7058 7059
GEN_HANDLER2_E(treclaim, "treclaim", 0x1F, 0x0E, 0x1D, 0x03E0F800, \
               PPC_NONE, PPC2_TM),
GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \
               PPC_NONE, PPC2_TM),
7060 7061 7062 7063 7064 7065 7066 7067 7068 7069

#include "translate/fp-ops.inc.c"

#include "translate/vmx-ops.inc.c"

#include "translate/vsx-ops.inc.c"

#include "translate/dfp-ops.inc.c"

#include "translate/spe-ops.inc.c"
7070 7071
};

7072
#include "helper_regs.h"
7073
#include "translate_init.inc.c"
B
bellard 已提交
7074

7075
/*****************************************************************************/
7076
/* Misc PowerPC helpers */
7077 7078
void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                        int flags)
B
bellard 已提交
7079
{
7080 7081 7082
#define RGPL  4
#define RFPL  4

7083 7084
    PowerPCCPU *cpu = POWERPC_CPU(cs);
    CPUPPCState *env = &cpu->env;
B
bellard 已提交
7085 7086
    int i;

7087
    cpu_fprintf(f, "NIP " TARGET_FMT_lx "   LR " TARGET_FMT_lx " CTR "
T
Tristan Gingold 已提交
7088 7089 7090
                TARGET_FMT_lx " XER " TARGET_FMT_lx " CPU#%d\n",
                env->nip, env->lr, env->ctr, cpu_read_xer(env),
                cs->cpu_index);
7091
    cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx "  HF "
7092 7093 7094
                TARGET_FMT_lx " iidx %d didx %d\n",
                env->msr, env->spr[SPR_HID0],
                env->hflags, env->immu_idx, env->dmmu_idx);
7095
#if !defined(NO_TIMER_DUMP)
7096
    cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
7097
#if !defined(CONFIG_USER_ONLY)
7098
                " DECR %08" PRIu32
7099 7100
#endif
                "\n",
J
j_mayer 已提交
7101
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
7102 7103 7104 7105
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
7106
#endif
7107
    for (i = 0; i < 32; i++) {
7108 7109
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
B
Blue Swirl 已提交
7110
        cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
7111
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
7112
            cpu_fprintf(f, "\n");
7113
    }
7114
    cpu_fprintf(f, "CR ");
7115
    for (i = 0; i < 8; i++)
B
bellard 已提交
7116 7117
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
7118 7119 7120 7121 7122 7123 7124 7125
    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 已提交
7126
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
7127
    }
7128 7129
    cpu_fprintf(f, " ]             RES " TARGET_FMT_lx "\n",
                env->reserve_addr);
7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141

    if (flags & CPU_DUMP_FPU) {
        for (i = 0; i < 32; i++) {
            if ((i & (RFPL - 1)) == 0) {
                cpu_fprintf(f, "FPR%02d", i);
            }
            cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
            if ((i & (RFPL - 1)) == (RFPL - 1)) {
                cpu_fprintf(f, "\n");
            }
        }
        cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
B
bellard 已提交
7142
    }
7143

7144
#if !defined(CONFIG_USER_ONLY)
S
Scott Wood 已提交
7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159
    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]);

7160 7161 7162 7163 7164 7165 7166
#if defined(TARGET_PPC64)
    if (env->excp_model == POWERPC_EXCP_POWER7 ||
        env->excp_model == POWERPC_EXCP_POWER8) {
        cpu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n",
                    env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
    }
#endif
S
Scott Wood 已提交
7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199
    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 已提交
7200 7201 7202 7203 7204 7205
#if defined(TARGET_PPC64)
    if (env->flags & POWERPC_FLAG_CFAR) {
        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
    }
#endif

7206 7207 7208
    if (env->spr_cb[SPR_LPCR].name)
        cpu_fprintf(f, " LPCR " TARGET_FMT_lx "\n", env->spr[SPR_LPCR]);

7209
    switch (env->mmu_model) {
S
Scott Wood 已提交
7210 7211 7212 7213 7214
    case POWERPC_MMU_32B:
    case POWERPC_MMU_601:
    case POWERPC_MMU_SOFT_6xx:
    case POWERPC_MMU_SOFT_74xx:
#if defined(TARGET_PPC64)
7215 7216 7217 7218 7219
    case POWERPC_MMU_64B:
    case POWERPC_MMU_2_03:
    case POWERPC_MMU_2_06:
    case POWERPC_MMU_2_07:
    case POWERPC_MMU_3_00:
S
Scott Wood 已提交
7220
#endif
7221 7222 7223
        if (env->spr_cb[SPR_SDR1].name) { /* SDR1 Exists */
            cpu_fprintf(f, " SDR1 " TARGET_FMT_lx " ", env->spr[SPR_SDR1]);
        }
7224 7225 7226
        if (env->spr_cb[SPR_PTCR].name) { /* PTCR Exists */
            cpu_fprintf(f, " PTCR " TARGET_FMT_lx " ", env->spr[SPR_PTCR]);
        }
7227
        cpu_fprintf(f, "  DAR " TARGET_FMT_lx "  DSISR " TARGET_FMT_lx "\n",
A
Anton Blanchard 已提交
7228
                    env->spr[SPR_DAR], env->spr[SPR_DSISR]);
S
Scott Wood 已提交
7229
        break;
A
Alexander Graf 已提交
7230
    case POWERPC_MMU_BOOKE206:
S
Scott Wood 已提交
7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248
        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;
    }
7249
#endif
B
bellard 已提交
7250

7251 7252
#undef RGPL
#undef RFPL
B
bellard 已提交
7253 7254
}

7255 7256
void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
                             fprintf_function cpu_fprintf, int flags)
7257 7258
{
#if defined(DO_PPC_STATISTICS)
7259
    PowerPCCPU *cpu = POWERPC_CPU(cs);
A
Anthony Liguori 已提交
7260
    opc_handler_t **t1, **t2, **t3, *handler;
7261 7262
    int op1, op2, op3;

7263
    t1 = cpu->env.opcodes;
7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276
    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 已提交
7277
                                    "%016" PRIx64 " %" PRId64 "\n",
7278 7279 7280 7281 7282 7283 7284 7285
                                    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 已提交
7286
                                "%016" PRIx64 " %" PRId64 "\n",
7287 7288 7289 7290 7291 7292 7293
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
B
Blue Swirl 已提交
7294 7295
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016" PRIx64
                        " %" PRId64 "\n",
7296 7297 7298 7299 7300 7301 7302
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

7303
static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
B
bellard 已提交
7304
{
7305
    DisasContext *ctx = container_of(dcbase, DisasContext, base);
7306
    CPUPPCState *env = cs->env_ptr;
7307 7308 7309 7310 7311 7312 7313
    int bound;

    ctx->exception = POWERPC_EXCP_NONE;
    ctx->spr_cb = env->spr_cb;
    ctx->pr = msr_pr;
    ctx->mem_idx = env->dmmu_idx;
    ctx->dr = msr_dr;
7314
#if !defined(CONFIG_USER_ONLY)
7315
    ctx->hv = msr_hv || !env->has_hv_mode;
7316
#endif
7317 7318 7319 7320 7321 7322
    ctx->insns_flags = env->insns_flags;
    ctx->insns_flags2 = env->insns_flags2;
    ctx->access_type = -1;
    ctx->need_access_type = !(env->mmu_model & POWERPC_MMU_64B);
    ctx->le_mode = !!(env->hflags & (1 << MSR_LE));
    ctx->default_tcg_memop_mask = ctx->le_mode ? MO_LE : MO_BE;
7323
#if defined(TARGET_PPC64)
7324 7325
    ctx->sf_mode = msr_is_64bit(env, env->msr);
    ctx->has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
7326
#endif
7327 7328 7329
    ctx->lazy_tlb_flush = env->mmu_model == POWERPC_MMU_32B
        || env->mmu_model == POWERPC_MMU_601
        || (env->mmu_model & POWERPC_MMU_64B);
7330

7331
    ctx->fpu_enabled = !!msr_fp;
7332
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
7333
        ctx->spe_enabled = !!msr_spe;
7334
    else
7335
        ctx->spe_enabled = false;
7336
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
7337
        ctx->altivec_enabled = !!msr_vr;
7338
    else
7339
        ctx->altivec_enabled = false;
T
Tom Musta 已提交
7340
    if ((env->flags & POWERPC_FLAG_VSX) && msr_vsx) {
7341
        ctx->vsx_enabled = !!msr_vsx;
T
Tom Musta 已提交
7342
    } else {
7343
        ctx->vsx_enabled = false;
T
Tom Musta 已提交
7344
    }
7345 7346
#if defined(TARGET_PPC64)
    if ((env->flags & POWERPC_FLAG_TM) && msr_tm) {
7347
        ctx->tm_enabled = !!msr_tm;
7348
    } else {
7349
        ctx->tm_enabled = false;
7350 7351
    }
#endif
7352
    ctx->gtse = !!(env->spr[SPR_LPCR] & LPCR_GTSE);
7353
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
7354
        ctx->singlestep_enabled = CPU_SINGLE_STEP;
7355
    else
7356
        ctx->singlestep_enabled = 0;
7357
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
7358 7359 7360
        ctx->singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(ctx->base.singlestep_enabled)) {
        ctx->singlestep_enabled |= GDBSTUB_SINGLE_STEP;
7361
    }
7362
#if defined (DO_SINGLE_STEP) && 0
7363 7364 7365
    /* Single step trace mode */
    msr_se = 1;
#endif
7366

7367
    bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
7368
    ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418
}

static void ppc_tr_tb_start(DisasContextBase *db, CPUState *cs)
{
}

static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
{
    tcg_gen_insn_start(dcbase->pc_next);
}

static bool ppc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
                                    const CPUBreakpoint *bp)
{
    DisasContext *ctx = container_of(dcbase, DisasContext, base);

    gen_debug_exception(ctx);
    /* The address covered by the breakpoint must be included in
       [tb->pc, tb->pc + tb->size) in order to for it to be
       properly cleared -- thus we increment the PC here so that
       the logic setting tb->size below does the right thing.  */
    ctx->base.pc_next += 4;
    return true;
}

static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
    DisasContext *ctx = container_of(dcbase, DisasContext, base);
    CPUPPCState *env = cs->env_ptr;
    opc_handler_t **table, *handler;

    LOG_DISAS("----------------\n");
    LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
              ctx->base.pc_next, ctx->mem_idx, (int)msr_ir);

    if (unlikely(need_byteswap(ctx))) {
        ctx->opcode = bswap32(cpu_ldl_code(env, ctx->base.pc_next));
    } else {
        ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
    }
    LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n",
              ctx->opcode, opc1(ctx->opcode), opc2(ctx->opcode),
              opc3(ctx->opcode), opc4(ctx->opcode),
              ctx->le_mode ? "little" : "big");
    ctx->base.pc_next += 4;
    table = env->opcodes;
    handler = table[opc1(ctx->opcode)];
    if (is_indirect_opcode(handler)) {
        table = ind_table(handler);
        handler = table[opc2(ctx->opcode)];
B
bellard 已提交
7419 7420
        if (is_indirect_opcode(handler)) {
            table = ind_table(handler);
7421
            handler = table[opc3(ctx->opcode)];
B
bellard 已提交
7422 7423
            if (is_indirect_opcode(handler)) {
                table = ind_table(handler);
7424
                handler = table[opc4(ctx->opcode)];
B
bellard 已提交
7425 7426
            }
        }
7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437
    }
    /* Is opcode *REALLY* valid ? */
    if (unlikely(handler->handler == &gen_invalid)) {
        qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
                      "%02x - %02x - %02x - %02x (%08x) "
                      TARGET_FMT_lx " %d\n",
                      opc1(ctx->opcode), opc2(ctx->opcode),
                      opc3(ctx->opcode), opc4(ctx->opcode),
                      ctx->opcode, ctx->base.pc_next - 4, (int)msr_ir);
    } else {
        uint32_t inval;
7438

7439 7440 7441 7442 7443 7444
        if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE)
                     && Rc(ctx->opcode))) {
            inval = handler->inval2;
        } else {
            inval = handler->inval1;
        }
7445

7446 7447 7448 7449 7450 7451 7452 7453 7454 7455
        if (unlikely((ctx->opcode & inval) != 0)) {
            qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
                          "%02x - %02x - %02x - %02x (%08x) "
                          TARGET_FMT_lx "\n", ctx->opcode & inval,
                          opc1(ctx->opcode), opc2(ctx->opcode),
                          opc3(ctx->opcode), opc4(ctx->opcode),
                          ctx->opcode, ctx->base.pc_next - 4);
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
            ctx->base.is_jmp = DISAS_NORETURN;
            return;
B
bellard 已提交
7456
        }
7457 7458
    }
    (*(handler->handler))(ctx);
7459
#if defined(DO_PPC_STATISTICS)
7460
    handler->count++;
7461
#endif
7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474
    /* Check trace mode exceptions */
    if (unlikely(ctx->singlestep_enabled & CPU_SINGLE_STEP &&
                 (ctx->base.pc_next <= 0x100 || ctx->base.pc_next > 0xF00) &&
                 ctx->exception != POWERPC_SYSCALL &&
                 ctx->exception != POWERPC_EXCP_TRAP &&
                 ctx->exception != POWERPC_EXCP_BRANCH)) {
        gen_exception_nip(ctx, POWERPC_EXCP_TRACE, ctx->base.pc_next);
    }

    if (tcg_check_temp_count()) {
        qemu_log("Opcode %02x %02x %02x %02x (%08x) leaked "
                 "temporaries\n", opc1(ctx->opcode), opc2(ctx->opcode),
                 opc3(ctx->opcode), opc4(ctx->opcode), ctx->opcode);
7475
    }
7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489

    ctx->base.is_jmp = ctx->exception == POWERPC_EXCP_NONE ?
        DISAS_NEXT : DISAS_NORETURN;
}

static void ppc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
{
    DisasContext *ctx = container_of(dcbase, DisasContext, base);

    if (ctx->exception == POWERPC_EXCP_NONE) {
        gen_goto_tb(ctx, 0, ctx->base.pc_next);
    } else if (ctx->exception != POWERPC_EXCP_BRANCH) {
        if (unlikely(ctx->base.singlestep_enabled)) {
            gen_debug_exception(ctx);
7490
        }
7491
        /* Generate the return instruction */
7492
        tcg_gen_exit_tb(NULL, 0);
7493
    }
7494 7495 7496 7497 7498 7499 7500
}

static void ppc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
{
    qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
    log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
}
7501

7502 7503 7504 7505 7506 7507 7508 7509 7510
static const TranslatorOps ppc_tr_ops = {
    .init_disas_context = ppc_tr_init_disas_context,
    .tb_start           = ppc_tr_tb_start,
    .insn_start         = ppc_tr_insn_start,
    .breakpoint_check   = ppc_tr_breakpoint_check,
    .translate_insn     = ppc_tr_translate_insn,
    .tb_stop            = ppc_tr_tb_stop,
    .disas_log          = ppc_tr_disas_log,
};
7511

7512 7513 7514 7515 7516
void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
{
    DisasContext ctx;

    translator_loop(&ppc_tr_ops, &ctx.base, cs, tb);
B
bellard 已提交
7517 7518
}

7519 7520
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb,
                          target_ulong *data)
A
aurel32 已提交
7521
{
7522
    env->nip = data[0];
A
aurel32 已提交
7523
}