translate.c 307.8 KB
Newer Older
B
bellard 已提交
1
/*
2
 *  PowerPC emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
B
bellard 已提交
5 6 7 8 9 10 11 12 13 14 15 16 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
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
B
bellard 已提交
19
 */
B
bellard 已提交
20 21 22 23 24 25
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

B
bellard 已提交
26
#include "cpu.h"
B
bellard 已提交
27
#include "exec-all.h"
B
bellard 已提交
28
#include "disas.h"
B
bellard 已提交
29
#include "tcg-op.h"
30
#include "qemu-common.h"
A
aurel32 已提交
31
#include "host-utils.h"
B
bellard 已提交
32

P
pbrook 已提交
33 34 35 36
#include "helper.h"
#define GEN_HELPER 1
#include "helper.h"

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

41
/* Include definitions for instructions classes and implementations flags */
A
aurel32 已提交
42
//#define DO_SINGLE_STEP
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 */
P
pbrook 已提交
55
static TCGv_ptr cpu_env;
56
static char cpu_reg_names[10*3 + 22*4 /* GPR */
A
aurel32 已提交
57
#if !defined(TARGET_PPC64)
58
    + 10*4 + 22*5 /* SPE GPRh */
A
aurel32 已提交
59
#endif
A
aurel32 已提交
60
    + 10*4 + 22*5 /* FPR */
A
aurel32 已提交
61 62
    + 2*(10*6 + 22*7) /* AVRh, AVRl */
    + 8*5 /* CRF */];
A
aurel32 已提交
63 64 65 66
static TCGv cpu_gpr[32];
#if !defined(TARGET_PPC64)
static TCGv cpu_gprh[32];
#endif
P
pbrook 已提交
67 68 69
static TCGv_i64 cpu_fpr[32];
static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
static TCGv_i32 cpu_crf[8];
A
aurel32 已提交
70
static TCGv cpu_nip;
71
static TCGv cpu_msr;
A
aurel32 已提交
72 73
static TCGv cpu_ctr;
static TCGv cpu_lr;
A
aurel32 已提交
74
static TCGv cpu_xer;
75
static TCGv cpu_reserve;
P
pbrook 已提交
76
static TCGv_i32 cpu_fpscr;
A
aurel32 已提交
77
static TCGv_i32 cpu_access_type;
A
aurel32 已提交
78

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

void ppc_translate_init(void)
{
A
aurel32 已提交
83 84
    int i;
    char* p;
P
pbrook 已提交
85
    static int done_init = 0;
A
aurel32 已提交
86

P
pbrook 已提交
87 88
    if (done_init)
        return;
A
aurel32 已提交
89

P
pbrook 已提交
90 91
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");

A
aurel32 已提交
92
    p = cpu_reg_names;
A
aurel32 已提交
93 94 95

    for (i = 0; i < 8; i++) {
        sprintf(p, "crf%d", i);
P
pbrook 已提交
96 97
        cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
                                            offsetof(CPUState, crf[i]), p);
A
aurel32 已提交
98 99 100
        p += 5;
    }

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

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

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

128
        sprintf(p, "avr%dL", i);
129 130 131 132
#ifdef WORDS_BIGENDIAN
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                             offsetof(CPUState, avr[i].u64[1]), p);
#else
P
pbrook 已提交
133
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
134 135
                                             offsetof(CPUState, avr[i].u64[0]), p);
#endif
136
        p += (i < 10) ? 6 : 7;
A
aurel32 已提交
137
    }
A
aurel32 已提交
138

P
pbrook 已提交
139
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
140 141
                                 offsetof(CPUState, nip), "nip");

142 143 144
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
                                 offsetof(CPUState, msr), "msr");

P
pbrook 已提交
145
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
146 147
                                 offsetof(CPUState, ctr), "ctr");

P
pbrook 已提交
148
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
149 150
                                offsetof(CPUState, lr), "lr");

P
pbrook 已提交
151
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
152 153
                                 offsetof(CPUState, xer), "xer");

154 155 156
    cpu_reserve = tcg_global_mem_new(TCG_AREG0,
                                     offsetof(CPUState, reserve), "reserve");

P
pbrook 已提交
157 158
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
                                       offsetof(CPUState, fpscr), "fpscr");
159

A
aurel32 已提交
160 161 162
    cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
                                             offsetof(CPUState, access_type), "access_type");

A
aurel32 已提交
163
    /* register helpers */
P
pbrook 已提交
164
#define GEN_HELPER 2
A
aurel32 已提交
165 166
#include "helper.h"

P
pbrook 已提交
167 168 169
    done_init = 1;
}

B
bellard 已提交
170 171 172
/* internal defines */
typedef struct DisasContext {
    struct TranslationBlock *tb;
B
bellard 已提交
173
    target_ulong nip;
B
bellard 已提交
174
    uint32_t opcode;
175
    uint32_t exception;
B
bellard 已提交
176 177
    /* Routine used to access memory */
    int mem_idx;
A
aurel32 已提交
178
    int access_type;
B
bellard 已提交
179
    /* Translation flags */
A
aurel32 已提交
180
    int le_mode;
181 182
#if defined(TARGET_PPC64)
    int sf_mode;
183
#endif
B
bellard 已提交
184
    int fpu_enabled;
185
    int altivec_enabled;
186
    int spe_enabled;
187
    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
188
    int singlestep_enabled;
B
bellard 已提交
189 190
} DisasContext;

191
struct opc_handler_t {
B
bellard 已提交
192 193
    /* invalid bits */
    uint32_t inval;
194
    /* instruction type */
195
    uint64_t type;
B
bellard 已提交
196 197
    /* handler */
    void (*handler)(DisasContext *ctx);
198
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
199
    const char *oname;
200 201
#endif
#if defined(DO_PPC_STATISTICS)
202 203
    uint64_t count;
#endif
204
};
B
bellard 已提交
205

206 207 208
static always_inline void gen_reset_fpstatus (void)
{
#ifdef CONFIG_SOFTFLOAT
209
    gen_helper_reset_fpstatus();
210 211 212
#endif
}

213
static always_inline void gen_compute_fprf (TCGv_i64 arg, int set_fprf, int set_rc)
214
{
215
    TCGv_i32 t0 = tcg_temp_new_i32();
A
aurel32 已提交
216

217 218
    if (set_fprf != 0) {
        /* This case might be optimized later */
219
        tcg_gen_movi_i32(t0, 1);
A
aurel32 已提交
220
        gen_helper_compute_fprf(t0, arg, t0);
P
pbrook 已提交
221
        if (unlikely(set_rc)) {
222
            tcg_gen_mov_i32(cpu_crf[1], t0);
P
pbrook 已提交
223
        }
A
aurel32 已提交
224
        gen_helper_float_check_status();
225 226
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
227
        tcg_gen_movi_i32(t0, 0);
A
aurel32 已提交
228
        gen_helper_compute_fprf(t0, arg, t0);
229
        tcg_gen_mov_i32(cpu_crf[1], t0);
230
    }
A
aurel32 已提交
231

232
    tcg_temp_free_i32(t0);
233 234
}

A
aurel32 已提交
235
static always_inline void gen_set_access_type (DisasContext *ctx, int access_type)
A
aurel32 已提交
236
{
A
aurel32 已提交
237 238 239 240
    if (ctx->access_type != access_type) {
        tcg_gen_movi_i32(cpu_access_type, access_type);
        ctx->access_type = access_type;
    }
A
aurel32 已提交
241 242
}

243
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
244 245 246
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
A
aurel32 已提交
247
        tcg_gen_movi_tl(cpu_nip, nip);
248 249
    else
#endif
A
aurel32 已提交
250
        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
251 252
}

A
aurel32 已提交
253 254 255 256 257 258 259 260 261 262 263 264 265
static always_inline void gen_exception_err (DisasContext *ctx, uint32_t excp, uint32_t error)
{
    TCGv_i32 t0, t1;
    if (ctx->exception == POWERPC_EXCP_NONE) {
        gen_update_nip(ctx, ctx->nip);
    }
    t0 = tcg_const_i32(excp);
    t1 = tcg_const_i32(error);
    gen_helper_raise_exception_err(t0, t1);
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
    ctx->exception = (excp);
}
266

A
aurel32 已提交
267 268 269 270 271 272 273 274 275 276 277
static always_inline void gen_exception (DisasContext *ctx, uint32_t excp)
{
    TCGv_i32 t0;
    if (ctx->exception == POWERPC_EXCP_NONE) {
        gen_update_nip(ctx, ctx->nip);
    }
    t0 = tcg_const_i32(excp);
    gen_helper_raise_exception(t0);
    tcg_temp_free_i32(t0);
    ctx->exception = (excp);
}
278

A
aurel32 已提交
279 280 281
static always_inline void gen_debug_exception (DisasContext *ctx)
{
    TCGv_i32 t0;
B
blueswir1 已提交
282 283 284

    if (ctx->exception != POWERPC_EXCP_BRANCH)
        gen_update_nip(ctx, ctx->nip);
A
aurel32 已提交
285 286 287 288
    t0 = tcg_const_i32(EXCP_DEBUG);
    gen_helper_raise_exception(t0);
    tcg_temp_free_i32(t0);
}
289

A
aurel32 已提交
290 291 292 293
static always_inline void gen_inval_exception (DisasContext *ctx, uint32_t error)
{
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
}
294

295
/* Stop translation */
A
aurel32 已提交
296
static always_inline void gen_stop_exception (DisasContext *ctx)
297
{
298
    gen_update_nip(ctx, ctx->nip);
299
    ctx->exception = POWERPC_EXCP_STOP;
300 301
}

302
/* No need to update nip here, as execution flow will change */
A
aurel32 已提交
303
static always_inline void gen_sync_exception (DisasContext *ctx)
304
{
305
    ctx->exception = POWERPC_EXCP_SYNC;
306 307
}

B
bellard 已提交
308 309 310 311 312
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
static void gen_##name (DisasContext *ctx);                                   \
GEN_OPCODE(name, opc1, opc2, opc3, inval, type);                              \
static void gen_##name (DisasContext *ctx)

313 314 315 316 317
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
static void gen_##name (DisasContext *ctx);                                   \
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type);                       \
static void gen_##name (DisasContext *ctx)

B
bellard 已提交
318 319
typedef struct opcode_t {
    unsigned char opc1, opc2, opc3;
T
ths 已提交
320
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
321 322 323 324
    unsigned char pad[5];
#else
    unsigned char pad[1];
#endif
B
bellard 已提交
325
    opc_handler_t handler;
326
    const char *oname;
B
bellard 已提交
327 328
} opcode_t;

329
/*****************************************************************************/
B
bellard 已提交
330 331
/***                           Instruction decoding                        ***/
#define EXTRACT_HELPER(name, shift, nb)                                       \
332
static always_inline uint32_t name (uint32_t opcode)                          \
B
bellard 已提交
333 334 335 336 337
{                                                                             \
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
}

#define EXTRACT_SHELPER(name, shift, nb)                                      \
338
static always_inline int32_t name (uint32_t opcode)                           \
B
bellard 已提交
339
{                                                                             \
340
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
B
bellard 已提交
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
}

/* Opcode part 1 */
EXTRACT_HELPER(opc1, 26, 6);
/* Opcode part 2 */
EXTRACT_HELPER(opc2, 1, 5);
/* Opcode part 3 */
EXTRACT_HELPER(opc3, 6, 5);
/* Update Cr0 flags */
EXTRACT_HELPER(Rc, 0, 1);
/* Destination */
EXTRACT_HELPER(rD, 21, 5);
/* Source */
EXTRACT_HELPER(rS, 21, 5);
/* First operand */
EXTRACT_HELPER(rA, 16, 5);
/* Second operand */
EXTRACT_HELPER(rB, 11, 5);
/* Third operand */
EXTRACT_HELPER(rC, 6, 5);
/***                               Get CRn                                 ***/
EXTRACT_HELPER(crfD, 23, 3);
EXTRACT_HELPER(crfS, 18, 3);
EXTRACT_HELPER(crbD, 21, 5);
EXTRACT_HELPER(crbA, 16, 5);
EXTRACT_HELPER(crbB, 11, 5);
/* SPR / TBL */
368
EXTRACT_HELPER(_SPR, 11, 10);
369
static always_inline uint32_t SPR (uint32_t opcode)
370 371 372 373 374
{
    uint32_t sprn = _SPR(opcode);

    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
}
B
bellard 已提交
375 376 377 378 379 380
/***                              Get constants                            ***/
EXTRACT_HELPER(IMM, 12, 8);
/* 16 bits signed immediate value */
EXTRACT_SHELPER(SIMM, 0, 16);
/* 16 bits unsigned immediate value */
EXTRACT_HELPER(UIMM, 0, 16);
381 382
/* 5 bits signed immediate value */
EXTRACT_HELPER(SIMM5, 16, 5);
383 384
/* 5 bits signed immediate value */
EXTRACT_HELPER(UIMM5, 16, 5);
B
bellard 已提交
385 386 387 388
/* Bit count */
EXTRACT_HELPER(NB, 11, 5);
/* Shift count */
EXTRACT_HELPER(SH, 11, 5);
A
aurel32 已提交
389 390
/* Vector shift count */
EXTRACT_HELPER(VSH, 6, 4);
B
bellard 已提交
391 392 393 394
/* Mask start */
EXTRACT_HELPER(MB, 6, 5);
/* Mask end */
EXTRACT_HELPER(ME, 1, 5);
B
bellard 已提交
395 396
/* Trap operand */
EXTRACT_HELPER(TO, 21, 5);
B
bellard 已提交
397 398 399 400

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

B
bellard 已提交
403 404 405 406
/***                            Jump target decoding                       ***/
/* Displacement */
EXTRACT_SHELPER(d, 0, 16);
/* Immediate address */
407
static always_inline target_ulong LI (uint32_t opcode)
B
bellard 已提交
408 409 410 411
{
    return (opcode >> 0) & 0x03FFFFFC;
}

412
static always_inline uint32_t BD (uint32_t opcode)
B
bellard 已提交
413 414 415 416 417 418 419 420 421 422 423 424
{
    return (opcode >> 0) & 0xFFFC;
}

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

/* Create a mask between <start> and <end> bits */
425
static always_inline target_ulong MASK (uint32_t start, uint32_t end)
B
bellard 已提交
426
{
427
    target_ulong ret;
B
bellard 已提交
428

429 430
#if defined(TARGET_PPC64)
    if (likely(start == 0)) {
431
        ret = UINT64_MAX << (63 - end);
432
    } else if (likely(end == 63)) {
433
        ret = UINT64_MAX >> start;
434 435 436
    }
#else
    if (likely(start == 0)) {
437
        ret = UINT32_MAX << (31  - end);
438
    } else if (likely(end == 31)) {
439
        ret = UINT32_MAX >> start;
440 441 442 443 444 445 446 447
    }
#endif
    else {
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
            (((target_ulong)(-1ULL) >> (end)) >> 1);
        if (unlikely(start > end))
            return ~ret;
    }
B
bellard 已提交
448 449 450 451

    return ret;
}

452 453 454
/*****************************************************************************/
/* PowerPC Instructions types definitions                                    */
enum {
455
    PPC_NONE           = 0x0000000000000000ULL,
456
    /* PowerPC base instructions set                                         */
457 458
    PPC_INSNS_BASE     = 0x0000000000000001ULL,
    /*   integer operations instructions                                     */
459
#define PPC_INTEGER PPC_INSNS_BASE
460
    /*   flow control instructions                                           */
461
#define PPC_FLOW    PPC_INSNS_BASE
462
    /*   virtual memory instructions                                         */
463
#define PPC_MEM     PPC_INSNS_BASE
464
    /*   ld/st with reservation instructions                                 */
465
#define PPC_RES     PPC_INSNS_BASE
466
    /*   spr/msr access instructions                                         */
467
#define PPC_MISC    PPC_INSNS_BASE
468 469
    /* Deprecated instruction sets                                           */
    /*   Original POWER instruction set                                      */
470
    PPC_POWER          = 0x0000000000000002ULL,
471
    /*   POWER2 instruction set extension                                    */
472
    PPC_POWER2         = 0x0000000000000004ULL,
473
    /*   Power RTC support                                                   */
474
    PPC_POWER_RTC      = 0x0000000000000008ULL,
475
    /*   Power-to-PowerPC bridge (601)                                       */
476
    PPC_POWER_BR       = 0x0000000000000010ULL,
477
    /* 64 bits PowerPC instruction set                                       */
478
    PPC_64B            = 0x0000000000000020ULL,
479
    /*   New 64 bits extensions (PowerPC 2.0x)                               */
480
    PPC_64BX           = 0x0000000000000040ULL,
481
    /*   64 bits hypervisor extensions                                       */
482
    PPC_64H            = 0x0000000000000080ULL,
483
    /*   New wait instruction (PowerPC 2.0x)                                 */
484
    PPC_WAIT           = 0x0000000000000100ULL,
485
    /*   Time base mftb instruction                                          */
486
    PPC_MFTB           = 0x0000000000000200ULL,
487 488 489

    /* Fixed-point unit extensions                                           */
    /*   PowerPC 602 specific                                                */
490
    PPC_602_SPEC       = 0x0000000000000400ULL,
491 492 493 494 495 496
    /*   isel instruction                                                    */
    PPC_ISEL           = 0x0000000000000800ULL,
    /*   popcntb instruction                                                 */
    PPC_POPCNTB        = 0x0000000000001000ULL,
    /*   string load / store                                                 */
    PPC_STRING         = 0x0000000000002000ULL,
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513

    /* Floating-point unit extensions                                        */
    /*   Optional floating point instructions                                */
    PPC_FLOAT          = 0x0000000000010000ULL,
    /* New floating-point extensions (PowerPC 2.0x)                          */
    PPC_FLOAT_EXT      = 0x0000000000020000ULL,
    PPC_FLOAT_FSQRT    = 0x0000000000040000ULL,
    PPC_FLOAT_FRES     = 0x0000000000080000ULL,
    PPC_FLOAT_FRSQRTE  = 0x0000000000100000ULL,
    PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
    PPC_FLOAT_FSEL     = 0x0000000000400000ULL,
    PPC_FLOAT_STFIWX   = 0x0000000000800000ULL,

    /* Vector/SIMD extensions                                                */
    /*   Altivec support                                                     */
    PPC_ALTIVEC        = 0x0000000001000000ULL,
    /*   PowerPC 2.03 SPE extension                                          */
514
    PPC_SPE            = 0x0000000002000000ULL,
515 516 517 518
    /*   PowerPC 2.03 SPE single-precision floating-point extension          */
    PPC_SPE_SINGLE     = 0x0000000004000000ULL,
    /*   PowerPC 2.03 SPE double-precision floating-point extension          */
    PPC_SPE_DOUBLE     = 0x0000000008000000ULL,
519

520
    /* Optional memory control instructions                                  */
521 522 523 524 525 526 527 528 529
    PPC_MEM_TLBIA      = 0x0000000010000000ULL,
    PPC_MEM_TLBIE      = 0x0000000020000000ULL,
    PPC_MEM_TLBSYNC    = 0x0000000040000000ULL,
    /*   sync instruction                                                    */
    PPC_MEM_SYNC       = 0x0000000080000000ULL,
    /*   eieio instruction                                                   */
    PPC_MEM_EIEIO      = 0x0000000100000000ULL,

    /* Cache control instructions                                            */
530
    PPC_CACHE          = 0x0000000200000000ULL,
531
    /*   icbi instruction                                                    */
532
    PPC_CACHE_ICBI     = 0x0000000400000000ULL,
533
    /*   dcbz instruction with fixed cache line size                         */
534
    PPC_CACHE_DCBZ     = 0x0000000800000000ULL,
535
    /*   dcbz instruction with tunable cache line size                       */
536
    PPC_CACHE_DCBZT    = 0x0000001000000000ULL,
537
    /*   dcba instruction                                                    */
538 539 540
    PPC_CACHE_DCBA     = 0x0000002000000000ULL,
    /*   Freescale cache locking instructions                                */
    PPC_CACHE_LOCK     = 0x0000004000000000ULL,
541 542 543

    /* MMU related extensions                                                */
    /*   external control instructions                                       */
544
    PPC_EXTERN         = 0x0000010000000000ULL,
545
    /*   segment register access instructions                                */
546
    PPC_SEGMENT        = 0x0000020000000000ULL,
547
    /*   PowerPC 6xx TLB management instructions                             */
548
    PPC_6xx_TLB        = 0x0000040000000000ULL,
549
    /* PowerPC 74xx TLB management instructions                              */
550
    PPC_74xx_TLB       = 0x0000080000000000ULL,
551
    /*   PowerPC 40x TLB management instructions                             */
552
    PPC_40x_TLB        = 0x0000100000000000ULL,
553
    /*   segment register access instructions for PowerPC 64 "bridge"        */
554
    PPC_SEGMENT_64B    = 0x0000200000000000ULL,
555
    /*   SLB management                                                      */
556
    PPC_SLBI           = 0x0000400000000000ULL,
557

558
    /* Embedded PowerPC dedicated instructions                               */
559
    PPC_WRTEE          = 0x0001000000000000ULL,
560
    /* PowerPC 40x exception model                                           */
561
    PPC_40x_EXCP       = 0x0002000000000000ULL,
562
    /* PowerPC 405 Mac instructions                                          */
563
    PPC_405_MAC        = 0x0004000000000000ULL,
564
    /* PowerPC 440 specific instructions                                     */
565
    PPC_440_SPEC       = 0x0008000000000000ULL,
566
    /* BookE (embedded) PowerPC specification                                */
567 568 569 570 571 572 573
    PPC_BOOKE          = 0x0010000000000000ULL,
    /* mfapidi instruction                                                   */
    PPC_MFAPIDI        = 0x0020000000000000ULL,
    /* tlbiva instruction                                                    */
    PPC_TLBIVA         = 0x0040000000000000ULL,
    /* tlbivax instruction                                                   */
    PPC_TLBIVAX        = 0x0080000000000000ULL,
574
    /* PowerPC 4xx dedicated instructions                                    */
575
    PPC_4xx_COMMON     = 0x0100000000000000ULL,
576
    /* PowerPC 40x ibct instructions                                         */
577
    PPC_40x_ICBT       = 0x0200000000000000ULL,
578
    /* rfmci is not implemented in all BookE PowerPC                         */
579 580 581 582 583 584 585
    PPC_RFMCI          = 0x0400000000000000ULL,
    /* rfdi instruction                                                      */
    PPC_RFDI           = 0x0800000000000000ULL,
    /* DCR accesses                                                          */
    PPC_DCR            = 0x1000000000000000ULL,
    /* DCR extended accesse                                                  */
    PPC_DCRX           = 0x2000000000000000ULL,
586
    /* user-mode DCR access, implemented in PowerPC 460                      */
587
    PPC_DCRUX          = 0x4000000000000000ULL,
588 589 590 591
};

/*****************************************************************************/
/* PowerPC instructions table                                                */
592 593 594 595 596
#if HOST_LONG_BITS == 64
#define OPC_ALIGN 8
#else
#define OPC_ALIGN 4
#endif
B
bellard 已提交
597
#if defined(__APPLE__)
598
#define OPCODES_SECTION                                                       \
599
    __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
600
#else
601
#define OPCODES_SECTION                                                       \
602
    __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
603 604
#endif

605
#if defined(DO_PPC_STATISTICS)
B
bellard 已提交
606
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
607
extern opcode_t opc_##name;                                                   \
608
OPCODES_SECTION opcode_t opc_##name = {                                       \
B
bellard 已提交
609 610 611
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
612
    .pad  = { 0, },                                                           \
B
bellard 已提交
613 614
    .handler = {                                                              \
        .inval   = invl,                                                      \
615
        .type = _typ,                                                         \
B
bellard 已提交
616
        .handler = &gen_##name,                                               \
617
        .oname = stringify(name),                                             \
B
bellard 已提交
618
    },                                                                        \
619
    .oname = stringify(name),                                                 \
B
bellard 已提交
620
}
621 622 623 624 625 626 627 628 629 630 631 632 633 634
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
OPCODES_SECTION opcode_t opc_##name = {                                       \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval   = invl,                                                      \
        .type = _typ,                                                         \
        .handler = &gen_##name,                                               \
        .oname = onam,                                                        \
    },                                                                        \
    .oname = onam,                                                            \
}
635 636
#else
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
637
extern opcode_t opc_##name;                                                   \
638 639 640 641 642 643 644 645 646 647 648 649
OPCODES_SECTION opcode_t opc_##name = {                                       \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval   = invl,                                                      \
        .type = _typ,                                                         \
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = stringify(name),                                                 \
}
650
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
651
extern opcode_t opc_##name;                                                   \
652 653 654 655 656 657 658 659 660 661 662 663
OPCODES_SECTION opcode_t opc_##name = {                                       \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval   = invl,                                                      \
        .type = _typ,                                                         \
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = onam,                                                            \
}
664
#endif
B
bellard 已提交
665 666

#define GEN_OPCODE_MARK(name)                                                 \
667
extern opcode_t opc_##name;                                                   \
668
OPCODES_SECTION opcode_t opc_##name = {                                       \
B
bellard 已提交
669 670 671
    .opc1 = 0xFF,                                                             \
    .opc2 = 0xFF,                                                             \
    .opc3 = 0xFF,                                                             \
672
    .pad  = { 0, },                                                           \
B
bellard 已提交
673 674
    .handler = {                                                              \
        .inval   = 0x00000000,                                                \
675
        .type = 0x00,                                                         \
B
bellard 已提交
676 677
        .handler = NULL,                                                      \
    },                                                                        \
678
    .oname = stringify(name),                                                 \
B
bellard 已提交
679 680
}

681 682 683 684 685 686 687 688 689 690 691
/* SPR load/store helpers */
static always_inline void gen_load_spr(TCGv t, int reg)
{
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
}

static always_inline void gen_store_spr(int reg, TCGv t)
{
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
}

B
bellard 已提交
692 693 694 695
/* Start opcode list */
GEN_OPCODE_MARK(start);

/* Invalid instruction */
696 697
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
{
A
aurel32 已提交
698
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
699 700
}

B
bellard 已提交
701 702
static opc_handler_t invalid_handler = {
    .inval   = 0xFFFFFFFF,
703
    .type    = PPC_NONE,
B
bellard 已提交
704 705 706
    .handler = gen_invalid,
};

707 708
/***                           Integer comparison                          ***/

709
static always_inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
710 711 712
{
    int l1, l2, l3;

713 714
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
715 716 717 718 719 720
    tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);

    l1 = gen_new_label();
    l2 = gen_new_label();
    l3 = gen_new_label();
    if (s) {
721 722
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
723
    } else {
724 725
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
726 727 728 729 730 731 732 733 734 735 736
    }
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
    tcg_gen_br(l3);
    gen_set_label(l1);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
    tcg_gen_br(l3);
    gen_set_label(l2);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
    gen_set_label(l3);
}

737
static always_inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
738
{
739 740 741
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
742 743 744
}

#if defined(TARGET_PPC64)
745
static always_inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
746
{
747
    TCGv t0, t1;
P
pbrook 已提交
748 749
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
750
    if (s) {
751 752
        tcg_gen_ext32s_tl(t0, arg0);
        tcg_gen_ext32s_tl(t1, arg1);
753
    } else {
754 755
        tcg_gen_ext32u_tl(t0, arg0);
        tcg_gen_ext32u_tl(t1, arg1);
756
    }
757 758 759
    gen_op_cmp(t0, t1, s, crf);
    tcg_temp_free(t1);
    tcg_temp_free(t0);
760 761
}

762
static always_inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
763
{
764 765 766
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp32(arg0, t0, s, crf);
    tcg_temp_free(t0);
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
}
#endif

static always_inline void gen_set_Rc0 (DisasContext *ctx, TCGv reg)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode))
        gen_op_cmpi32(reg, 0, 1, 0);
    else
#endif
        gen_op_cmpi(reg, 0, 1, 0);
}

/* cmp */
GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     1, crfD(ctx->opcode));
    else
#endif
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   1, crfD(ctx->opcode));
}

/* cmpi */
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                      1, crfD(ctx->opcode));
    else
#endif
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                    1, crfD(ctx->opcode));
}

/* cmpl */
GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     0, crfD(ctx->opcode));
    else
#endif
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   0, crfD(ctx->opcode));
}

/* cmpli */
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                      0, crfD(ctx->opcode));
    else
#endif
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                    0, crfD(ctx->opcode));
}

/* isel (PowerPC 2.03 specification) */
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
{
    int l1, l2;
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;
P
pbrook 已提交
838
    TCGv_i32 t0;
839 840 841 842 843

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

    mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
844
    t0 = tcg_temp_new_i32();
845 846
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
847 848 849 850 851 852 853 854
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    else
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    gen_set_label(l2);
P
pbrook 已提交
855
    tcg_temp_free_i32(t0);
856 857
}

B
bellard 已提交
858 859
/***                           Integer arithmetic                          ***/

860 861 862 863
static always_inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, TCGv arg1, TCGv arg2, int sub)
{
    int l1;
    TCGv t0;
B
bellard 已提交
864

865 866 867
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
P
pbrook 已提交
868
    t0 = tcg_temp_local_new();
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
    tcg_gen_xor_tl(t0, arg0, arg1);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    tcg_gen_xor_tl(t0, arg1, arg2);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    gen_set_label(l1);
    tcg_temp_free(t0);
B
bellard 已提交
890 891
}

892 893 894
static always_inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, TCGv arg2, int sub)
{
    int l1 = gen_new_label();
895 896

#if defined(TARGET_PPC64)
897 898
    if (!(ctx->sf_mode)) {
        TCGv t0, t1;
P
pbrook 已提交
899 900
        t0 = tcg_temp_new();
        t1 = tcg_temp_new();
901

902 903 904 905
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_ext32u_tl(t1, arg2);
        if (sub) {
            tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
A
aurel32 已提交
906
        } else {
907 908
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
        }
909 910 911 912
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
        gen_set_label(l1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
913 914
    } else
#endif
915 916 917 918 919 920 921 922
    {
        if (sub) {
            tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
        } else {
            tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
        }
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
        gen_set_label(l1);
923
    }
924 925
}

926 927 928 929 930
/* Common add function */
static always_inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                           int add_ca, int compute_ca, int compute_ov)
{
    TCGv t0, t1;
931

932
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
933
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
934 935
        t0 = ret;
    } else {
P
pbrook 已提交
936
        t0 = tcg_temp_local_new();
937
    }
B
bellard 已提交
938

939
    if (add_ca) {
P
pbrook 已提交
940
        t1 = tcg_temp_local_new();
941 942 943
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
    }
B
bellard 已提交
944

945 946 947 948 949 950 951 952 953 954
    if (compute_ca && compute_ov) {
        /* Start with XER CA and OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
    } else if (compute_ca) {
        /* Start with XER CA disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    } else if (compute_ov) {
        /* Start with XER OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
B
bellard 已提交
955

956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972
    tcg_gen_add_tl(t0, arg1, arg2);

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

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

P
pbrook 已提交
973
    if (!TCGV_EQUAL(t0, ret)) {
974 975 976
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
977
}
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER)                  \
{                                                                             \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
                     add_ca, compute_ca, compute_ov);                         \
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
                                add_ca, compute_ca, compute_ov)               \
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER)                  \
{                                                                             \
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
                     add_ca, compute_ca, compute_ov);                         \
    tcg_temp_free(t0);                                                        \
}

/* add  add.  addo  addo. */
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
/* addc  addc.  addco  addco. */
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
/* adde  adde.  addeo  addeo. */
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
/* addme  addme.  addmeo  addmeo.  */
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
/* addze  addze.  addzeo  addzeo.*/
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
/* addi */
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1015
{
1016 1017 1018 1019 1020 1021 1022 1023
    target_long simm = SIMM(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        /* li case */
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
    } else {
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
    }
1024
}
1025 1026 1027
/* addic  addic.*/
static always_inline void gen_op_addic (DisasContext *ctx, TCGv ret, TCGv arg1,
                                        int compute_Rc0)
1028
{
1029 1030 1031 1032 1033 1034
    target_long simm = SIMM(ctx->opcode);

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

    if (likely(simm != 0)) {
P
pbrook 已提交
1035
        TCGv t0 = tcg_temp_local_new();
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
        tcg_gen_addi_tl(t0, arg1, simm);
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    } else {
        tcg_gen_mov_tl(ret, arg1);
    }
    if (compute_Rc0) {
        gen_set_Rc0(ctx, ret);
    }
1046
}
1047
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1048
{
1049
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1050
}
1051
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1052
{
1053
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1054
}
1055 1056
/* addis */
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1057
{
1058 1059 1060 1061 1062 1063 1064 1065
    target_long simm = SIMM(ctx->opcode);

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

static always_inline void gen_op_arith_divw (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                             int sign, int compute_ov)
1070
{
1071 1072
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
1073 1074
    TCGv_i32 t0 = tcg_temp_local_new_i32();
    TCGv_i32 t1 = tcg_temp_local_new_i32();
1075

1076 1077 1078
    tcg_gen_trunc_tl_i32(t0, arg1);
    tcg_gen_trunc_tl_i32(t1, arg2);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
1079
    if (sign) {
1080 1081 1082
        int l3 = gen_new_label();
        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
1083
        gen_set_label(l3);
1084
        tcg_gen_div_i32(t0, t0, t1);
1085
    } else {
1086
        tcg_gen_divu_i32(t0, t0, t1);
1087 1088 1089 1090 1091 1092 1093
    }
    if (compute_ov) {
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
    if (sign) {
1094
        tcg_gen_sari_i32(t0, t0, 31);
1095 1096 1097 1098 1099 1100 1101
    } else {
        tcg_gen_movi_i32(t0, 0);
    }
    if (compute_ov) {
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    }
    gen_set_label(l2);
1102
    tcg_gen_extu_i32_tl(ret, t0);
P
pbrook 已提交
1103 1104
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
1105 1106
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
1107
}
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
/* Div functions */
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)                  \
{                                                                             \
    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);
1122
#if defined(TARGET_PPC64)
1123 1124
static always_inline void gen_op_arith_divd (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                             int sign, int compute_ov)
1125
{
1126 1127
    int l1 = gen_new_label();
    int l2 = gen_new_label();
1128 1129 1130

    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
    if (sign) {
1131
        int l3 = gen_new_label();
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
        tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
        tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
        gen_set_label(l3);
        tcg_gen_div_i64(ret, arg1, arg2);
    } else {
        tcg_gen_divu_i64(ret, arg1, arg2);
    }
    if (compute_ov) {
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
    if (sign) {
        tcg_gen_sari_i64(ret, arg1, 63);
    } else {
        tcg_gen_movi_i64(ret, 0);
    }
    if (compute_ov) {
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    }
    gen_set_label(l2);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
1155
}
1156 1157 1158
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)                      \
{                                                                             \
1159 1160 1161
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      sign, compute_ov);                                      \
1162 1163 1164 1165 1166 1167 1168
}
/* divwu  divwu.  divwuo  divwuo.   */
GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
/* divw  divw.  divwo  divwo.   */
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1169
#endif
1170 1171 1172

/* mulhw  mulhw. */
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER)
1173
{
P
pbrook 已提交
1174
    TCGv_i64 t0, t1;
1175

P
pbrook 已提交
1176 1177
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
#else
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
P
pbrook 已提交
1190 1191
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1192 1193
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1194
}
1195 1196
/* mulhwu  mulhwu.  */
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER)
1197
{
P
pbrook 已提交
1198
    TCGv_i64 t0, t1;
1199

P
pbrook 已提交
1200 1201
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1202
#if defined(TARGET_PPC64)
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
    tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
#else
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
P
pbrook 已提交
1214 1215
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1216 1217
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1218
}
1219 1220
/* mullw  mullw. */
GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER)
1221
{
1222 1223
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
1224
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1225 1226
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1227
}
1228 1229
/* mullwo  mullwo. */
GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER)
1230
{
1231
    int l1;
P
pbrook 已提交
1232
    TCGv_i64 t0, t1;
1233

P
pbrook 已提交
1234 1235
    t0 = tcg_temp_new_i64();
    t1 = tcg_temp_new_i64();
1236 1237 1238 1239 1240 1241 1242 1243 1244
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
#else
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1245
#endif
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
    tcg_gen_mul_i64(t0, t0, t1);
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
#else
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_ext32s_i64(t1, t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
#endif
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    gen_set_label(l1);
P
pbrook 已提交
1257 1258
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
1259 1260
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1261
}
1262 1263
/* mulli */
GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1264
{
1265 1266
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                    SIMM(ctx->opcode));
1267 1268
}
#if defined(TARGET_PPC64)
1269 1270 1271
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)                      \
{                                                                             \
P
pbrook 已提交
1272
    gen_helper_##name (cpu_gpr[rD(ctx->opcode)],                              \
1273 1274 1275
                       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)]);                           \
1276
}
1277 1278 1279 1280 1281 1282
/* mulhd  mulhd. */
GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
/* mulhdu  mulhdu. */
GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
/* mulld  mulld. */
GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B)
1283
{
1284 1285 1286 1287
    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)]);
1288
}
1289 1290
/* mulldo  mulldo. */
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1291
#endif
1292 1293

/* neg neg. nego nego. */
A
aurel32 已提交
1294
static always_inline void gen_op_arith_neg (DisasContext *ctx, TCGv ret, TCGv arg1, int ov_check)
1295
{
A
aurel32 已提交
1296 1297
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
1298
    TCGv t0 = tcg_temp_local_new();
1299
#if defined(TARGET_PPC64)
1300
    if (ctx->sf_mode) {
A
aurel32 已提交
1301
        tcg_gen_mov_tl(t0, arg1);
A
aurel32 已提交
1302 1303 1304 1305 1306
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
    } else
#endif
    {
        tcg_gen_ext32s_tl(t0, arg1);
1307 1308 1309 1310 1311 1312 1313 1314
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
    }
    tcg_gen_neg_tl(ret, arg1);
    if (ov_check) {
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
    tcg_gen_br(l2);
    gen_set_label(l1);
A
aurel32 已提交
1315
    tcg_gen_mov_tl(ret, t0);
1316 1317 1318 1319
    if (ov_check) {
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    }
    gen_set_label(l2);
A
aurel32 已提交
1320
    tcg_temp_free(t0);
1321 1322 1323 1324
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, ret);
}
GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER)
1325
{
A
aurel32 已提交
1326
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1327
}
1328
GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER)
B
bellard 已提交
1329
{
A
aurel32 已提交
1330
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
B
bellard 已提交
1331
}
1332 1333 1334 1335

/* Common subf function */
static always_inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                            int add_ca, int compute_ca, int compute_ov)
B
bellard 已提交
1336
{
1337
    TCGv t0, t1;
1338

1339
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
1340
        (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1341
        t0 = ret;
J
j_mayer 已提交
1342
    } else {
P
pbrook 已提交
1343
        t0 = tcg_temp_local_new();
1344
    }
1345

1346
    if (add_ca) {
P
pbrook 已提交
1347
        t1 = tcg_temp_local_new();
1348 1349
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
1350
    }
B
bellard 已提交
1351

1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
    if (compute_ca && compute_ov) {
        /* Start with XER CA and OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
    } else if (compute_ca) {
        /* Start with XER CA disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    } else if (compute_ov) {
        /* Start with XER OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }

    if (add_ca) {
        tcg_gen_not_tl(t0, arg1);
        tcg_gen_add_tl(t0, t0, arg2);
        gen_op_arith_compute_ca(ctx, t0, arg2, 0);
        tcg_gen_add_tl(t0, t0, t1);
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
        tcg_temp_free(t1);
B
bellard 已提交
1370
    } else {
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
        tcg_gen_sub_tl(t0, arg2, arg1);
        if (compute_ca) {
            gen_op_arith_compute_ca(ctx, t0, arg2, 1);
        }
    }
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
    }

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

P
pbrook 已提交
1383
    if (!TCGV_EQUAL(t0, ret)) {
1384 1385
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
B
bellard 已提交
1386 1387
    }
}
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER)                  \
{                                                                             \
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      add_ca, compute_ca, compute_ov);                        \
}
/* Sub functions with one operand and one immediate */
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
                                add_ca, compute_ca, compute_ov)               \
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER)                  \
{                                                                             \
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], t0,                           \
                      add_ca, compute_ca, compute_ov);                        \
    tcg_temp_free(t0);                                                        \
}
/* subf  subf.  subfo  subfo. */
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
/* subfc  subfc.  subfco  subfco. */
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
/* subfe  subfe.  subfeo  subfo. */
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
/* subfme  subfme.  subfmeo  subfmeo.  */
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
/* subfze  subfze.  subfzeo  subfzeo.*/
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
B
bellard 已提交
1422 1423 1424
/* subfic */
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1425 1426
    /* Start with XER CA and OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
P
pbrook 已提交
1427
    TCGv t0 = tcg_temp_local_new();
1428 1429 1430 1431 1432 1433
    TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
    tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
    gen_op_arith_compute_ca(ctx, t0, t1, 1);
    tcg_temp_free(t1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
B
bellard 已提交
1434 1435 1436
}

/***                            Integer logical                            ***/
1437 1438
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)                          \
B
bellard 已提交
1439
{                                                                             \
1440 1441
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
       cpu_gpr[rB(ctx->opcode)]);                                             \
1442
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1443
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1444 1445
}

1446
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
1447
GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)                          \
B
bellard 已提交
1448
{                                                                             \
1449
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1450
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1451
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1452 1453 1454
}

/* and & and. */
1455
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
B
bellard 已提交
1456
/* andc & andc. */
1457
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
B
bellard 已提交
1458
/* andi. */
1459
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1460
{
1461 1462
    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 已提交
1463 1464
}
/* andis. */
1465
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1466
{
1467 1468
    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 已提交
1469 1470
}
/* cntlzw */
1471 1472
GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER)
{
P
pbrook 已提交
1473
    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1474
    if (unlikely(Rc(ctx->opcode) != 0))
P
pbrook 已提交
1475
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1476
}
B
bellard 已提交
1477
/* eqv & eqv. */
1478
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
B
bellard 已提交
1479
/* extsb & extsb. */
1480
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
B
bellard 已提交
1481
/* extsh & extsh. */
1482
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
B
bellard 已提交
1483
/* nand & nand. */
1484
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
B
bellard 已提交
1485
/* nor & nor. */
1486
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
B
bellard 已提交
1487
/* or & or. */
1488 1489
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
{
1490 1491 1492 1493 1494 1495 1496
    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) {
1497 1498 1499 1500
        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]);
1501
        if (unlikely(Rc(ctx->opcode) != 0))
1502
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1503
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1504
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1505 1506
#if defined(TARGET_PPC64)
    } else {
1507 1508
        int prio = 0;

1509 1510 1511
        switch (rs) {
        case 1:
            /* Set process priority to low */
1512
            prio = 2;
1513 1514 1515
            break;
        case 6:
            /* Set process priority to medium-low */
1516
            prio = 3;
1517 1518 1519
            break;
        case 2:
            /* Set process priority to normal */
1520
            prio = 4;
1521
            break;
1522 1523
#if !defined(CONFIG_USER_ONLY)
        case 31:
A
aurel32 已提交
1524
            if (ctx->mem_idx > 0) {
1525
                /* Set process priority to very low */
1526
                prio = 1;
1527 1528 1529
            }
            break;
        case 5:
A
aurel32 已提交
1530
            if (ctx->mem_idx > 0) {
1531
                /* Set process priority to medium-hight */
1532
                prio = 5;
1533 1534 1535
            }
            break;
        case 3:
A
aurel32 已提交
1536
            if (ctx->mem_idx > 0) {
1537
                /* Set process priority to high */
1538
                prio = 6;
1539 1540 1541
            }
            break;
        case 7:
A
aurel32 已提交
1542
            if (ctx->mem_idx > 1) {
1543
                /* Set process priority to very high */
1544
                prio = 7;
1545 1546 1547
            }
            break;
#endif
1548 1549 1550 1551
        default:
            /* nop */
            break;
        }
1552
        if (prio) {
P
pbrook 已提交
1553
            TCGv t0 = tcg_temp_new();
1554
            gen_load_spr(t0, SPR_PPR);
1555 1556
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1557
            gen_store_spr(SPR_PPR, t0);
1558
            tcg_temp_free(t0);
1559
        }
1560
#endif
1561 1562
    }
}
B
bellard 已提交
1563
/* orc & orc. */
1564
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
B
bellard 已提交
1565
/* xor & xor. */
1566 1567 1568
GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
{
    /* Optimisation for "set to zero" case */
1569
    if (rS(ctx->opcode) != rB(ctx->opcode))
A
aurel32 已提交
1570
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1571 1572
    else
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1573
    if (unlikely(Rc(ctx->opcode) != 0))
1574
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1575
}
B
bellard 已提交
1576 1577 1578
/* ori */
GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1579
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1580

1581 1582
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
1583
        /* XXX: should handle special NOPs for POWER series */
1584
        return;
1585
    }
1586
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1587 1588 1589 1590
}
/* oris */
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1591
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1592

1593 1594 1595
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1596
    }
1597
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1598 1599 1600 1601
}
/* xori */
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1602
    target_ulong uimm = UIMM(ctx->opcode);
1603 1604 1605 1606 1607

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
1608
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1609 1610 1611 1612
}
/* xoris */
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1613
    target_ulong uimm = UIMM(ctx->opcode);
1614 1615 1616 1617 1618

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
1619
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
B
bellard 已提交
1620
}
1621
/* popcntb : PowerPC 2.03 specification */
1622
GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB)
1623 1624 1625
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
P
pbrook 已提交
1626
        gen_helper_popcntb_64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1627 1628
    else
#endif
P
pbrook 已提交
1629
        gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1630 1631 1632 1633
}

#if defined(TARGET_PPC64)
/* extsw & extsw. */
1634
GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1635
/* cntlzd */
1636 1637
GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B)
{
P
pbrook 已提交
1638
    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1639 1640 1641
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
1642 1643
#endif

B
bellard 已提交
1644 1645 1646 1647
/***                             Integer rotate                            ***/
/* rlwimi & rlwimi. */
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1648
    uint32_t mb, me, sh;
B
bellard 已提交
1649 1650 1651

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1652
    sh = SH(ctx->opcode);
1653 1654 1655 1656
    if (likely(sh == 0 && mb == 0 && me == 31)) {
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
    } else {
        target_ulong mask;
P
pbrook 已提交
1657 1658
        TCGv t1;
        TCGv t0 = tcg_temp_new();
1659
#if defined(TARGET_PPC64)
P
pbrook 已提交
1660 1661 1662 1663 1664
        TCGv_i32 t2 = tcg_temp_new_i32();
        tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_rotli_i32(t2, t2, sh);
        tcg_gen_extu_i32_i64(t0, t2);
        tcg_temp_free_i32(t2);
1665 1666 1667
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1668
#if defined(TARGET_PPC64)
1669 1670
        mb += 32;
        me += 32;
1671
#endif
1672
        mask = MASK(mb, me);
P
pbrook 已提交
1673
        t1 = tcg_temp_new();
1674 1675 1676 1677 1678 1679
        tcg_gen_andi_tl(t0, t0, mask);
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
    }
1680
    if (unlikely(Rc(ctx->opcode) != 0))
1681
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1682 1683 1684 1685 1686
}
/* rlwinm & rlwinm. */
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    uint32_t mb, me, sh;
1687

B
bellard 已提交
1688 1689 1690
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1691 1692 1693 1694 1695

    if (likely(mb == 0 && me == (31 - sh))) {
        if (likely(sh == 0)) {
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
        } else {
P
pbrook 已提交
1696
            TCGv t0 = tcg_temp_new();
1697 1698 1699 1700
            tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
            tcg_gen_shli_tl(t0, t0, sh);
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
            tcg_temp_free(t0);
B
bellard 已提交
1701
        }
1702
    } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
P
pbrook 已提交
1703
        TCGv t0 = tcg_temp_new();
1704 1705 1706 1707 1708
        tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_shri_tl(t0, t0, mb);
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
        tcg_temp_free(t0);
    } else {
P
pbrook 已提交
1709
        TCGv t0 = tcg_temp_new();
1710
#if defined(TARGET_PPC64)
P
pbrook 已提交
1711
        TCGv_i32 t1 = tcg_temp_new_i32();
1712 1713 1714
        tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_rotli_i32(t1, t1, sh);
        tcg_gen_extu_i32_i64(t0, t1);
P
pbrook 已提交
1715
        tcg_temp_free_i32(t1);
1716 1717 1718
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1719
#if defined(TARGET_PPC64)
1720 1721
        mb += 32;
        me += 32;
1722
#endif
1723 1724 1725
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
        tcg_temp_free(t0);
    }
1726
    if (unlikely(Rc(ctx->opcode) != 0))
1727
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1728 1729 1730 1731 1732
}
/* rlwnm & rlwnm. */
GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    uint32_t mb, me;
1733 1734
    TCGv t0;
#if defined(TARGET_PPC64)
P
pbrook 已提交
1735
    TCGv_i32 t1, t2;
1736
#endif
B
bellard 已提交
1737 1738 1739

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1740
    t0 = tcg_temp_new();
1741
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1742
#if defined(TARGET_PPC64)
P
pbrook 已提交
1743 1744
    t1 = tcg_temp_new_i32();
    t2 = tcg_temp_new_i32();
1745 1746 1747 1748
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_trunc_i64_i32(t2, t0);
    tcg_gen_rotl_i32(t1, t1, t2);
    tcg_gen_extu_i32_i64(t0, t1);
P
pbrook 已提交
1749 1750
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
1751 1752 1753
#else
    tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
#endif
1754 1755 1756 1757 1758
    if (unlikely(mb != 0 || me != 31)) {
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
1759
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1760
    } else {
1761
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
B
bellard 已提交
1762
    }
1763
    tcg_temp_free(t0);
1764
    if (unlikely(Rc(ctx->opcode) != 0))
1765
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1766 1767
}

1768 1769
#if defined(TARGET_PPC64)
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
1770
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1771 1772 1773
{                                                                             \
    gen_##name(ctx, 0);                                                       \
}                                                                             \
1774 1775
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1776 1777 1778 1779
{                                                                             \
    gen_##name(ctx, 1);                                                       \
}
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
1780
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1781 1782 1783
{                                                                             \
    gen_##name(ctx, 0, 0);                                                    \
}                                                                             \
1784 1785
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1786 1787 1788
{                                                                             \
    gen_##name(ctx, 0, 1);                                                    \
}                                                                             \
1789 1790
GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1791 1792 1793
{                                                                             \
    gen_##name(ctx, 1, 0);                                                    \
}                                                                             \
1794 1795
GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1796 1797 1798
{                                                                             \
    gen_##name(ctx, 1, 1);                                                    \
}
J
j_mayer 已提交
1799

1800 1801
static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
                                      uint32_t me, uint32_t sh)
J
j_mayer 已提交
1802
{
1803 1804 1805 1806 1807
    if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
        tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
    } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
        tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
    } else {
P
pbrook 已提交
1808
        TCGv t0 = tcg_temp_new();
1809
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1810
        if (likely(mb == 0 && me == 63)) {
1811
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1812 1813
        } else {
            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
J
j_mayer 已提交
1814
        }
1815
        tcg_temp_free(t0);
J
j_mayer 已提交
1816 1817
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1818
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
J
j_mayer 已提交
1819
}
1820
/* rldicl - rldicl. */
1821
static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1822
{
J
j_mayer 已提交
1823
    uint32_t sh, mb;
1824

J
j_mayer 已提交
1825 1826
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1827
    gen_rldinm(ctx, mb, 63, sh);
1828
}
J
j_mayer 已提交
1829
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1830
/* rldicr - rldicr. */
1831
static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1832
{
J
j_mayer 已提交
1833
    uint32_t sh, me;
1834

J
j_mayer 已提交
1835 1836
    sh = SH(ctx->opcode) | (shn << 5);
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1837
    gen_rldinm(ctx, 0, me, sh);
1838
}
J
j_mayer 已提交
1839
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1840
/* rldic - rldic. */
1841
static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1842
{
J
j_mayer 已提交
1843
    uint32_t sh, mb;
1844

J
j_mayer 已提交
1845 1846
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1847 1848 1849 1850
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

1851 1852
static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
                                     uint32_t me)
J
j_mayer 已提交
1853
{
1854
    TCGv t0;
1855 1856 1857

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1858
    t0 = tcg_temp_new();
1859
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1860
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
J
j_mayer 已提交
1861
    if (unlikely(mb != 0 || me != 63)) {
1862 1863 1864 1865 1866
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    }
    tcg_temp_free(t0);
J
j_mayer 已提交
1867
    if (unlikely(Rc(ctx->opcode) != 0))
1868
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1869
}
J
j_mayer 已提交
1870

1871
/* rldcl - rldcl. */
1872
static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1873
{
J
j_mayer 已提交
1874
    uint32_t mb;
1875

J
j_mayer 已提交
1876
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1877
    gen_rldnm(ctx, mb, 63);
1878
}
1879
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1880
/* rldcr - rldcr. */
1881
static always_inline void gen_rldcr (DisasContext *ctx, int men)
1882
{
J
j_mayer 已提交
1883
    uint32_t me;
1884

J
j_mayer 已提交
1885
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1886
    gen_rldnm(ctx, 0, me);
1887
}
1888
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1889
/* rldimi - rldimi. */
1890
static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1891
{
1892
    uint32_t sh, mb, me;
1893

J
j_mayer 已提交
1894 1895
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
1896
    me = 63 - sh;
1897 1898 1899 1900 1901 1902
    if (unlikely(sh == 0 && mb == 0)) {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
    } else {
        TCGv t0, t1;
        target_ulong mask;

P
pbrook 已提交
1903
        t0 = tcg_temp_new();
1904
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
P
pbrook 已提交
1905
        t1 = tcg_temp_new();
1906 1907 1908 1909 1910 1911
        mask = MASK(mb, me);
        tcg_gen_andi_tl(t0, t0, mask);
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
J
j_mayer 已提交
1912 1913
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1914
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1915
}
1916
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1917 1918
#endif

B
bellard 已提交
1919 1920
/***                             Integer shift                             ***/
/* slw & slw. */
1921 1922
GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER)
{
1923
    TCGv t0;
1924 1925 1926 1927
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();

P
pbrook 已提交
1928
    t0 = tcg_temp_local_new();
A
aurel32 已提交
1929 1930
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
1931 1932 1933
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    tcg_gen_br(l2);
    gen_set_label(l1);
1934
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
1935 1936
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l2);
1937
    tcg_temp_free(t0);
1938 1939 1940
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
bellard 已提交
1941
/* sraw & sraw. */
1942 1943
GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER)
{
P
pbrook 已提交
1944 1945
    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1946 1947 1948
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
B
bellard 已提交
1949 1950 1951
/* srawi & srawi. */
GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
{
1952 1953 1954
    int sh = SH(ctx->opcode);
    if (sh != 0) {
        int l1, l2;
1955
        TCGv t0;
1956 1957
        l1 = gen_new_label();
        l2 = gen_new_label();
P
pbrook 已提交
1958
        t0 = tcg_temp_local_new();
1959 1960 1961 1962
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1963
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1964 1965
        tcg_gen_br(l2);
        gen_set_label(l1);
1966
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1967
        gen_set_label(l2);
1968 1969 1970
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
        tcg_temp_free(t0);
1971 1972
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1973
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1974
    }
1975
    if (unlikely(Rc(ctx->opcode) != 0))
1976
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1977 1978
}
/* srw & srw. */
1979 1980
GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER)
{
1981
    TCGv t0, t1;
1982 1983 1984
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();
1985

P
pbrook 已提交
1986
    t0 = tcg_temp_local_new();
A
aurel32 已提交
1987 1988
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
1989 1990 1991
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    tcg_gen_br(l2);
    gen_set_label(l1);
P
pbrook 已提交
1992
    t1 = tcg_temp_new();
1993 1994 1995
    tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t1, t0);
    tcg_temp_free(t1);
1996
    gen_set_label(l2);
1997
    tcg_temp_free(t0);
1998 1999 2000
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2001 2002
#if defined(TARGET_PPC64)
/* sld & sld. */
2003 2004
GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B)
{
2005
    TCGv t0;
2006 2007 2008 2009
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();

P
pbrook 已提交
2010
    t0 = tcg_temp_local_new();
A
aurel32 已提交
2011 2012
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
2013 2014 2015
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    tcg_gen_br(l2);
    gen_set_label(l1);
2016
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
2017
    gen_set_label(l2);
2018
    tcg_temp_free(t0);
2019 2020 2021
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2022
/* srad & srad. */
2023 2024
GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B)
{
P
pbrook 已提交
2025 2026
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2027 2028 2029
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2030
/* sradi & sradi. */
2031
static always_inline void gen_sradi (DisasContext *ctx, int n)
2032
{
2033
    int sh = SH(ctx->opcode) + (n << 5);
2034
    if (sh != 0) {
2035
        int l1, l2;
2036
        TCGv t0;
2037 2038
        l1 = gen_new_label();
        l2 = gen_new_label();
P
pbrook 已提交
2039
        t0 = tcg_temp_local_new();
2040
        tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
2041 2042
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2043
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
2044 2045
        tcg_gen_br(l2);
        gen_set_label(l1);
2046
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
2047
        gen_set_label(l2);
2048
        tcg_temp_free(t0);
2049 2050 2051
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
    } else {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2052
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
2053 2054
    }
    if (unlikely(Rc(ctx->opcode) != 0))
2055
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2056
}
2057
GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
2058 2059 2060
{
    gen_sradi(ctx, 0);
}
2061
GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
2062 2063 2064 2065
{
    gen_sradi(ctx, 1);
}
/* srd & srd. */
2066 2067
GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B)
{
2068
    TCGv t0;
2069 2070 2071 2072
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();

P
pbrook 已提交
2073
    t0 = tcg_temp_local_new();
A
aurel32 已提交
2074 2075
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
2076 2077 2078
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    tcg_gen_br(l2);
    gen_set_label(l1);
2079
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
2080
    gen_set_label(l2);
2081
    tcg_temp_free(t0);
2082 2083 2084
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2085
#endif
B
bellard 已提交
2086 2087

/***                       Floating-Point arithmetic                       ***/
2088
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
2089
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
2090
{                                                                             \
2091
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2092
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2093 2094
        return;                                                               \
    }                                                                         \
2095 2096
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2097
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2098 2099
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
                     cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
2100
    if (isfloat) {                                                            \
A
aurel32 已提交
2101
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2102
    }                                                                         \
A
aurel32 已提交
2103 2104
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf,                      \
                     Rc(ctx->opcode) != 0);                                   \
2105 2106
}

2107 2108 2109
#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
2110

2111 2112
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2113
{                                                                             \
2114
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2115
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2116 2117
        return;                                                               \
    }                                                                         \
2118 2119
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2120
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2121 2122
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
                     cpu_fpr[rB(ctx->opcode)]);                               \
2123
    if (isfloat) {                                                            \
A
aurel32 已提交
2124
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2125
    }                                                                         \
A
aurel32 已提交
2126 2127
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2128
}
2129 2130 2131
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2132

2133 2134
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2135
{                                                                             \
2136
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2137
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2138 2139
        return;                                                               \
    }                                                                         \
2140 2141
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2142
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2143 2144
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
                       cpu_fpr[rC(ctx->opcode)]);                             \
2145
    if (isfloat) {                                                            \
A
aurel32 已提交
2146
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2147
    }                                                                         \
A
aurel32 已提交
2148 2149
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2150
}
2151 2152 2153
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2154

2155
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2156
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
2157
{                                                                             \
2158
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2159
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2160 2161
        return;                                                               \
    }                                                                         \
2162 2163
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2164
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2165 2166 2167
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2168 2169
}

2170
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2171
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)                        \
2172
{                                                                             \
2173
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
2174
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
B
bellard 已提交
2175 2176
        return;                                                               \
    }                                                                         \
2177 2178
    /* NIP cannot be restored if the memory exception comes from an helper */ \
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2179
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2180 2181 2182
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2183 2184
}

2185
/* fadd - fadds */
2186
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2187
/* fdiv - fdivs */
2188
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2189
/* fmul - fmuls */
2190
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2191

2192
/* fre */
2193
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2194

2195
/* fres */
2196
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2197

2198
/* frsqrte */
2199 2200 2201
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
A
aurel32 已提交
2202
GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES)
2203
{
A
aurel32 已提交
2204
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2205
        gen_exception(ctx, POWERPC_EXCP_FPU);
A
aurel32 已提交
2206 2207
        return;
    }
2208 2209
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2210 2211 2212 2213
    gen_reset_fpstatus();
    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2214
}
B
bellard 已提交
2215

2216
/* fsel */
2217
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2218
/* fsub - fsubs */
2219
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2220 2221
/* Optional: */
/* fsqrt */
2222
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
2223
{
2224
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2225
        gen_exception(ctx, POWERPC_EXCP_FPU);
2226 2227
        return;
    }
2228 2229
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2230
    gen_reset_fpstatus();
A
aurel32 已提交
2231 2232
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2233
}
B
bellard 已提交
2234

2235
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
B
bellard 已提交
2236
{
2237
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2238
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2239 2240
        return;
    }
2241 2242
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2243
    gen_reset_fpstatus();
A
aurel32 已提交
2244 2245 2246
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
B
bellard 已提交
2247 2248 2249
}

/***                     Floating-Point multiply-and-add                   ***/
2250
/* fmadd - fmadds */
2251
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2252
/* fmsub - fmsubs */
2253
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2254
/* fnmadd - fnmadds */
2255
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2256
/* fnmsub - fnmsubs */
2257
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2258 2259 2260

/***                     Floating-Point round & convert                    ***/
/* fctiw */
2261
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2262
/* fctiwz */
2263
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2264
/* frsp */
2265
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
2266 2267
#if defined(TARGET_PPC64)
/* fcfid */
2268
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
2269
/* fctid */
2270
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2271
/* fctidz */
2272
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2273
#endif
B
bellard 已提交
2274

2275
/* frin */
2276
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2277
/* friz */
2278
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2279
/* frip */
2280
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2281
/* frim */
2282
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2283

B
bellard 已提交
2284 2285
/***                         Floating-Point compare                        ***/
/* fcmpo */
2286
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
B
bellard 已提交
2287
{
A
aurel32 已提交
2288
    TCGv_i32 crf;
2289
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2290
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2291 2292
        return;
    }
2293 2294
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2295
    gen_reset_fpstatus();
A
aurel32 已提交
2296 2297
    crf = tcg_const_i32(crfD(ctx->opcode));
    gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2298
    tcg_temp_free_i32(crf);
A
aurel32 已提交
2299
    gen_helper_float_check_status();
B
bellard 已提交
2300 2301 2302
}

/* fcmpu */
2303
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
B
bellard 已提交
2304
{
A
aurel32 已提交
2305
    TCGv_i32 crf;
2306
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2307
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2308 2309
        return;
    }
2310 2311
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2312
    gen_reset_fpstatus();
A
aurel32 已提交
2313 2314
    crf = tcg_const_i32(crfD(ctx->opcode));
    gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
A
aurel32 已提交
2315
    tcg_temp_free_i32(crf);
A
aurel32 已提交
2316
    gen_helper_float_check_status();
B
bellard 已提交
2317 2318
}

2319 2320
/***                         Floating-point move                           ***/
/* fabs */
2321 2322
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2323 2324

/* fmr  - fmr. */
2325
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2326 2327
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
{
2328
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2329
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2330 2331
        return;
    }
A
aurel32 已提交
2332 2333
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2334 2335 2336
}

/* fnabs */
2337 2338
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2339
/* fneg */
2340 2341
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2342

B
bellard 已提交
2343 2344 2345 2346
/***                  Floating-Point status & ctrl register                ***/
/* mcrfs */
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
{
2347 2348
    int bfa;

2349
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2350
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2351 2352
        return;
    }
2353
    bfa = 4 * (7 - crfS(ctx->opcode));
2354 2355
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
A
aurel32 已提交
2356
    tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
B
bellard 已提交
2357 2358 2359 2360 2361
}

/* mffs */
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
{
2362
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2363
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2364 2365
        return;
    }
2366
    gen_reset_fpstatus();
A
aurel32 已提交
2367 2368
    tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2369 2370 2371 2372 2373
}

/* mtfsb0 */
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
{
B
bellard 已提交
2374
    uint8_t crb;
2375

2376
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2377
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2378 2379
        return;
    }
A
aurel32 已提交
2380
    crb = 31 - crbD(ctx->opcode);
2381
    gen_reset_fpstatus();
A
aurel32 已提交
2382
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2383 2384 2385 2386
        TCGv_i32 t0;
        /* NIP cannot be restored if the memory exception comes from an helper */
        gen_update_nip(ctx, ctx->nip - 4);
        t0 = tcg_const_i32(crb);
A
aurel32 已提交
2387 2388 2389
        gen_helper_fpscr_clrbit(t0);
        tcg_temp_free_i32(t0);
    }
2390
    if (unlikely(Rc(ctx->opcode) != 0)) {
2391
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2392
    }
B
bellard 已提交
2393 2394 2395 2396 2397
}

/* mtfsb1 */
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
{
B
bellard 已提交
2398
    uint8_t crb;
2399

2400
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2401
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2402 2403
        return;
    }
A
aurel32 已提交
2404
    crb = 31 - crbD(ctx->opcode);
2405 2406
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
A
aurel32 已提交
2407
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2408 2409 2410 2411
        TCGv_i32 t0;
        /* NIP cannot be restored if the memory exception comes from an helper */
        gen_update_nip(ctx, ctx->nip - 4);
        t0 = tcg_const_i32(crb);
A
aurel32 已提交
2412
        gen_helper_fpscr_setbit(t0);
2413
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2414
    }
2415
    if (unlikely(Rc(ctx->opcode) != 0)) {
2416
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2417 2418
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2419
    gen_helper_float_check_status();
B
bellard 已提交
2420 2421 2422
}

/* mtfsf */
B
blueswir1 已提交
2423
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT)
B
bellard 已提交
2424
{
2425
    TCGv_i32 t0;
B
blueswir1 已提交
2426
    int L = ctx->opcode & 0x02000000;
A
aurel32 已提交
2427

2428
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2429
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2430 2431
        return;
    }
2432 2433
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2434
    gen_reset_fpstatus();
B
blueswir1 已提交
2435 2436 2437 2438
    if (L)
        t0 = tcg_const_i32(0xff);
    else
        t0 = tcg_const_i32(FM(ctx->opcode));
A
aurel32 已提交
2439
    gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
2440
    tcg_temp_free_i32(t0);
2441
    if (unlikely(Rc(ctx->opcode) != 0)) {
2442
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2443 2444
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2445
    gen_helper_float_check_status();
B
bellard 已提交
2446 2447 2448 2449 2450
}

/* mtfsfi */
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
{
2451
    int bf, sh;
2452 2453
    TCGv_i64 t0;
    TCGv_i32 t1;
2454

2455
    if (unlikely(!ctx->fpu_enabled)) {
A
aurel32 已提交
2456
        gen_exception(ctx, POWERPC_EXCP_FPU);
B
bellard 已提交
2457 2458
        return;
    }
2459 2460
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
2461 2462
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2463
    gen_reset_fpstatus();
2464
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
A
aurel32 已提交
2465 2466
    t1 = tcg_const_i32(1 << sh);
    gen_helper_store_fpscr(t0, t1);
2467 2468
    tcg_temp_free_i64(t0);
    tcg_temp_free_i32(t1);
2469
    if (unlikely(Rc(ctx->opcode) != 0)) {
2470
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2471 2472
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2473
    gen_helper_float_check_status();
B
bellard 已提交
2474 2475
}

2476 2477
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
A
aurel32 已提交
2478
static always_inline void gen_addr_imm_index (DisasContext *ctx, TCGv EA, target_long maskl)
2479 2480 2481
{
    target_long simm = SIMM(ctx->opcode);

2482
    simm &= ~maskl;
A
aurel32 已提交
2483 2484 2485 2486 2487 2488
    if (rA(ctx->opcode) == 0) {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_movi_tl(EA, (uint32_t)simm);
        } else
#endif
2489
        tcg_gen_movi_tl(EA, simm);
A
aurel32 已提交
2490
    } else if (likely(simm != 0)) {
2491
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
A
aurel32 已提交
2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    } else {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
        } else
#endif
2503
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
2504
    }
2505 2506
}

A
aurel32 已提交
2507
static always_inline void gen_addr_reg_index (DisasContext *ctx, TCGv EA)
2508
{
A
aurel32 已提交
2509 2510 2511 2512 2513 2514
    if (rA(ctx->opcode) == 0) {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
        } else
#endif
2515
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2516
    } else {
2517
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
A
aurel32 已提交
2518 2519 2520 2521 2522 2523
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
2524 2525
}

A
aurel32 已提交
2526
static always_inline void gen_addr_register (DisasContext *ctx, TCGv EA)
2527
{
A
aurel32 已提交
2528
    if (rA(ctx->opcode) == 0) {
2529
        tcg_gen_movi_tl(EA, 0);
A
aurel32 已提交
2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547
    } else {
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
        } else
#endif
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
    }
}

static always_inline void gen_addr_add (DisasContext *ctx, TCGv ret, TCGv arg1, target_long val)
{
    tcg_gen_addi_tl(ret, arg1, val);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode) {
        tcg_gen_ext32u_tl(ret, ret);
    }
#endif
2548 2549
}

2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567
static always_inline void gen_check_align (DisasContext *ctx, TCGv EA, int mask)
{
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1, t2;
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    tcg_gen_andi_tl(t0, EA, mask);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
    t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
    t2 = tcg_const_i32(0);
    gen_helper_raise_exception_err(t1, t2);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    gen_set_label(l1);
    tcg_temp_free(t0);
}

2568
/***                             Integer load                              ***/
A
aurel32 已提交
2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582
static always_inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
}

static always_inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
}

static always_inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2583
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2584
    }
A
aurel32 已提交
2585 2586
}

A
aurel32 已提交
2587
static always_inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2588
{
A
aurel32 已提交
2589 2590
    if (unlikely(ctx->le_mode)) {
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2591
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2592 2593 2594 2595
        tcg_gen_ext16s_tl(arg1, arg1);
    } else {
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2596 2597
}

A
aurel32 已提交
2598
static always_inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2599
{
A
aurel32 已提交
2600 2601
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2602
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2603
    }
A
aurel32 已提交
2604 2605
}

A
aurel32 已提交
2606 2607
#if defined(TARGET_PPC64)
static always_inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2608
{
B
blueswir1 已提交
2609
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2610
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2611 2612
        tcg_gen_bswap32_tl(arg1, arg1);
        tcg_gen_ext32s_tl(arg1, arg1);
A
aurel32 已提交
2613
    } else
A
aurel32 已提交
2614
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2615
}
A
aurel32 已提交
2616
#endif
A
aurel32 已提交
2617

A
aurel32 已提交
2618
static always_inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2619
{
A
aurel32 已提交
2620 2621
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2622
        tcg_gen_bswap64_i64(arg1, arg1);
A
aurel32 已提交
2623
    }
A
aurel32 已提交
2624 2625
}

A
aurel32 已提交
2626
static always_inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2627
{
A
aurel32 已提交
2628
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2629 2630
}

A
aurel32 已提交
2631
static always_inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2632
{
A
aurel32 已提交
2633 2634 2635
    if (unlikely(ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2636
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2637 2638 2639 2640 2641
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2642 2643
}

A
aurel32 已提交
2644
static always_inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2645
{
A
aurel32 已提交
2646
    if (unlikely(ctx->le_mode)) {
A
aurel32 已提交
2647 2648 2649
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2650 2651 2652 2653 2654
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2655 2656
}

A
aurel32 已提交
2657
static always_inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
A
aurel32 已提交
2658
{
A
aurel32 已提交
2659
    if (unlikely(ctx->le_mode)) {
P
pbrook 已提交
2660
        TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
2661
        tcg_gen_bswap64_i64(t0, arg1);
A
aurel32 已提交
2662
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
P
pbrook 已提交
2663
        tcg_temp_free_i64(t0);
A
aurel32 已提交
2664
    } else
A
aurel32 已提交
2665
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
A
aurel32 已提交
2666 2667
}

2668 2669
#define GEN_LD(name, ldop, opc, type)                                         \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
B
bellard 已提交
2670
{                                                                             \
A
aurel32 已提交
2671 2672 2673 2674 2675
    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 已提交
2676
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2677 2678
}

2679 2680
#define GEN_LDU(name, ldop, opc, type)                                        \
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
B
bellard 已提交
2681
{                                                                             \
A
aurel32 已提交
2682
    TCGv EA;                                                                  \
2683 2684
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2685
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2686
        return;                                                               \
2687
    }                                                                         \
A
aurel32 已提交
2688
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2689
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2690
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2691
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2692
    else                                                                      \
A
aurel32 已提交
2693 2694
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2695 2696
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2697 2698
}

2699 2700
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type)                     \
B
bellard 已提交
2701
{                                                                             \
A
aurel32 已提交
2702
    TCGv EA;                                                                  \
2703 2704
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
A
aurel32 已提交
2705
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2706
        return;                                                               \
2707
    }                                                                         \
A
aurel32 已提交
2708
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2709
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2710 2711
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2712 2713
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2714 2715
}

2716 2717
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
B
bellard 已提交
2718
{                                                                             \
A
aurel32 已提交
2719 2720 2721 2722 2723
    TCGv EA;                                                                  \
    gen_set_access_type(ctx, ACCESS_INT);                                     \
    EA = tcg_temp_new();                                                      \
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
A
aurel32 已提交
2724
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2725 2726
}

2727 2728 2729 2730 2731
#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 已提交
2732 2733

/* lbz lbzu lbzux lbzx */
2734
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2735
/* lha lhau lhaux lhax */
2736
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2737
/* lhz lhzu lhzux lhzx */
2738
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2739
/* lwz lwzu lwzux lwzx */
2740
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2741 2742
#if defined(TARGET_PPC64)
/* lwaux */
2743
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2744
/* lwax */
2745
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2746
/* ldux */
2747
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2748
/* ldx */
2749
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
2750 2751
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
{
A
aurel32 已提交
2752
    TCGv EA;
2753 2754 2755
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
A
aurel32 已提交
2756
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2757 2758 2759
            return;
        }
    }
A
aurel32 已提交
2760
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2761
    EA = tcg_temp_new();
A
aurel32 已提交
2762
    gen_addr_imm_index(ctx, EA, 0x03);
2763 2764
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2765
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2766 2767
    } else {
        /* ld - ldu */
A
aurel32 已提交
2768
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2769 2770
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2771 2772
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2773
}
2774 2775 2776 2777
/* lq */
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2778
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2779 2780
#else
    int ra, rd;
A
aurel32 已提交
2781
    TCGv EA;
2782 2783

    /* Restore CPU state */
A
aurel32 已提交
2784
    if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2785
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2786 2787 2788 2789 2790
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
A
aurel32 已提交
2791
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2792 2793
        return;
    }
A
aurel32 已提交
2794
    if (unlikely(ctx->le_mode)) {
2795
        /* Little-endian mode is not handled */
A
aurel32 已提交
2796
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2797 2798
        return;
    }
A
aurel32 已提交
2799
    gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2800
    EA = tcg_temp_new();
A
aurel32 已提交
2801 2802 2803 2804
    gen_addr_imm_index(ctx, EA, 0x0F);
    gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
    gen_addr_add(ctx, EA, EA, 8);
    gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
A
aurel32 已提交
2805
    tcg_temp_free(EA);
2806 2807
#endif
}
2808
#endif
B
bellard 已提交
2809 2810

/***                              Integer store                            ***/
2811 2812
#define GEN_ST(name, stop, opc, type)                                         \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
B
bellard 已提交
2813
{                                                                             \
A
aurel32 已提交
2814 2815 2816 2817 2818
    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 已提交
2819
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2820 2821
}

2822 2823
#define GEN_STU(name, stop, opc, type)                                        \
GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
B
bellard 已提交
2824
{                                                                             \
A
aurel32 已提交
2825
    TCGv EA;                                                                  \
2826
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2827
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2828
        return;                                                               \
2829
    }                                                                         \
A
aurel32 已提交
2830
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2831
    EA = tcg_temp_new();                                                      \
J
j_mayer 已提交
2832
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2833
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
J
j_mayer 已提交
2834
    else                                                                      \
A
aurel32 已提交
2835 2836
        gen_addr_imm_index(ctx, EA, 0);                                       \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2837 2838
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2839 2840
}

2841 2842
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type)                     \
B
bellard 已提交
2843
{                                                                             \
A
aurel32 已提交
2844
    TCGv EA;                                                                  \
2845
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
2846
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2847
        return;                                                               \
2848
    }                                                                         \
A
aurel32 已提交
2849
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2850
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
2851 2852
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2853 2854
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2855 2856
}

2857 2858
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
B
bellard 已提交
2859
{                                                                             \
A
aurel32 已提交
2860 2861 2862 2863 2864
    TCGv EA;                                                                  \
    gen_set_access_type(ctx, ACCESS_INT);                                     \
    EA = tcg_temp_new();                                                      \
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
A
aurel32 已提交
2865
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2866 2867
}

2868 2869 2870 2871 2872
#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 已提交
2873 2874

/* stb stbu stbux stbx */
2875
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
B
bellard 已提交
2876
/* sth sthu sthux sthx */
2877
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2878
/* stw stwu stwux stwx */
2879
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2880
#if defined(TARGET_PPC64)
2881 2882
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
2883
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2884
{
2885
    int rs;
A
aurel32 已提交
2886
    TCGv EA;
2887 2888 2889 2890

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
2891
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2892 2893
#else
        /* stq */
A
aurel32 已提交
2894
        if (unlikely(ctx->mem_idx == 0)) {
A
aurel32 已提交
2895
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2896 2897 2898
            return;
        }
        if (unlikely(rs & 1)) {
A
aurel32 已提交
2899
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2900 2901
            return;
        }
A
aurel32 已提交
2902
        if (unlikely(ctx->le_mode)) {
2903
            /* Little-endian mode is not handled */
A
aurel32 已提交
2904
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2905 2906
            return;
        }
A
aurel32 已提交
2907
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2908
        EA = tcg_temp_new();
A
aurel32 已提交
2909 2910 2911 2912
        gen_addr_imm_index(ctx, EA, 0x03);
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
        gen_addr_add(ctx, EA, EA, 8);
        gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
A
aurel32 已提交
2913
        tcg_temp_free(EA);
2914 2915 2916 2917 2918
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
A
aurel32 已提交
2919
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2920 2921 2922
                return;
            }
        }
A
aurel32 已提交
2923
        gen_set_access_type(ctx, ACCESS_INT);
P
pbrook 已提交
2924
        EA = tcg_temp_new();
A
aurel32 已提交
2925 2926
        gen_addr_imm_index(ctx, EA, 0x03);
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2927
        if (Rc(ctx->opcode))
A
aurel32 已提交
2928 2929
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
2930 2931 2932
    }
}
#endif
B
bellard 已提交
2933 2934
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
A
aurel32 已提交
2935
static void always_inline gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2936
{
A
aurel32 已提交
2937 2938
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2939
        tcg_gen_bswap16_tl(arg1, arg1);
A
aurel32 已提交
2940
    }
A
aurel32 已提交
2941
}
2942
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
A
aurel32 已提交
2943

B
bellard 已提交
2944
/* lwbrx */
A
aurel32 已提交
2945
static void always_inline gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2946
{
A
aurel32 已提交
2947 2948
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2949
        tcg_gen_bswap32_tl(arg1, arg1);
A
aurel32 已提交
2950
    }
A
aurel32 已提交
2951
}
2952
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
A
aurel32 已提交
2953

B
bellard 已提交
2954
/* sthbrx */
A
aurel32 已提交
2955
static void always_inline gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2956
{
A
aurel32 已提交
2957 2958 2959
    if (likely(!ctx->le_mode)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext16u_tl(t0, arg1);
A
aurel32 已提交
2960
        tcg_gen_bswap16_tl(t0, t0);
A
aurel32 已提交
2961 2962 2963 2964 2965
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2966
}
2967
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
A
aurel32 已提交
2968

B
bellard 已提交
2969
/* stwbrx */
A
aurel32 已提交
2970
static void always_inline gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
A
aurel32 已提交
2971
{
A
aurel32 已提交
2972
    if (likely(!ctx->le_mode)) {
A
aurel32 已提交
2973 2974 2975
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_bswap32_tl(t0, t0);
A
aurel32 已提交
2976 2977 2978 2979 2980
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
        tcg_temp_free(t0);
    } else {
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
    }
A
aurel32 已提交
2981
}
2982
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2983 2984 2985 2986 2987

/***                    Integer load and store multiple                    ***/
/* lmw */
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
A
aurel32 已提交
2988 2989 2990
    TCGv t0;
    TCGv_i32 t1;
    gen_set_access_type(ctx, ACCESS_INT);
2991
    /* NIP cannot be restored if the memory exception comes from an helper */
2992
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
2993 2994 2995
    t0 = tcg_temp_new();
    t1 = tcg_const_i32(rD(ctx->opcode));
    gen_addr_imm_index(ctx, t0, 0);
2996 2997 2998
    gen_helper_lmw(t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
2999 3000 3001 3002 3003
}

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

/***                    Integer load and store strings                     ***/
/* lswi */
3019
/* PowerPC32 specification says we must generate an exception if
3020 3021 3022 3023
 * 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...
 */
3024
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
B
bellard 已提交
3025
{
3026 3027
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3028 3029
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
3030
    int ra = rA(ctx->opcode);
B
bellard 已提交
3031 3032 3033 3034 3035
    int nr;

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

/* lswx */
3056
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
B
bellard 已提交
3057
{
A
aurel32 已提交
3058 3059 3060
    TCGv t0;
    TCGv_i32 t1, t2, t3;
    gen_set_access_type(ctx, ACCESS_INT);
3061
    /* NIP cannot be restored if the memory exception comes from an helper */
3062
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3063 3064 3065 3066 3067
    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));
3068 3069 3070 3071 3072
    gen_helper_lswx(t0, t1, t2, t3);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
B
bellard 已提交
3073 3074 3075
}

/* stswi */
3076
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
B
bellard 已提交
3077
{
A
aurel32 已提交
3078 3079
    TCGv t0;
    TCGv_i32 t1, t2;
B
bellard 已提交
3080
    int nb = NB(ctx->opcode);
A
aurel32 已提交
3081
    gen_set_access_type(ctx, ACCESS_INT);
3082
    /* NIP cannot be restored if the memory exception comes from an helper */
3083
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3084 3085
    t0 = tcg_temp_new();
    gen_addr_register(ctx, t0);
B
bellard 已提交
3086 3087
    if (nb == 0)
        nb = 32;
3088
    t1 = tcg_const_i32(nb);
A
aurel32 已提交
3089
    t2 = tcg_const_i32(rS(ctx->opcode));
3090 3091 3092 3093
    gen_helper_stsw(t0, t1, t2);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3094 3095 3096
}

/* stswx */
3097
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
B
bellard 已提交
3098
{
A
aurel32 已提交
3099 3100 3101
    TCGv t0;
    TCGv_i32 t1, t2;
    gen_set_access_type(ctx, ACCESS_INT);
3102
    /* NIP cannot be restored if the memory exception comes from an helper */
3103
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
3104 3105 3106
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    t1 = tcg_temp_new_i32();
3107 3108
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
    tcg_gen_andi_i32(t1, t1, 0x7F);
A
aurel32 已提交
3109
    t2 = tcg_const_i32(rS(ctx->opcode));
3110 3111 3112 3113
    gen_helper_stsw(t0, t1, t2);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
B
bellard 已提交
3114 3115 3116 3117
}

/***                        Memory synchronisation                         ***/
/* eieio */
3118
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
B
bellard 已提交
3119 3120 3121 3122
{
}

/* isync */
3123
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
B
bellard 已提交
3124
{
A
aurel32 已提交
3125
    gen_stop_exception(ctx);
B
bellard 已提交
3126 3127
}

3128
/* lwarx */
3129
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
B
bellard 已提交
3130
{
A
aurel32 已提交
3131 3132 3133 3134
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3135
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
3136
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
3137 3138
    tcg_gen_mov_tl(cpu_reserve, t0);
    tcg_temp_free(t0);
B
bellard 已提交
3139 3140 3141
}

/* stwcx. */
3142
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
B
bellard 已提交
3143
{
A
aurel32 已提交
3144 3145 3146 3147 3148
    int l1;
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3149 3150 3151 3152
    gen_check_align(ctx, t0, 0x03);
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
    tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
A
aurel32 已提交
3153
    l1 = gen_new_label();
3154 3155
    tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
A
aurel32 已提交
3156
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3157 3158 3159
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_reserve, -1);
    tcg_temp_free(t0);
B
bellard 已提交
3160 3161
}

J
j_mayer 已提交
3162 3163
#if defined(TARGET_PPC64)
/* ldarx */
3164
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
J
j_mayer 已提交
3165
{
A
aurel32 已提交
3166 3167 3168 3169
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3170
    gen_check_align(ctx, t0, 0x07);
A
aurel32 已提交
3171
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], t0);
3172 3173
    tcg_gen_mov_tl(cpu_reserve, t0);
    tcg_temp_free(t0);
J
j_mayer 已提交
3174 3175 3176
}

/* stdcx. */
3177
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
J
j_mayer 已提交
3178
{
A
aurel32 已提交
3179 3180 3181 3182 3183
    int l1;
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_RES);
    t0 = tcg_temp_local_new();
    gen_addr_reg_index(ctx, t0);
3184 3185 3186 3187
    gen_check_align(ctx, t0, 0x07);
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
    tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
A
aurel32 已提交
3188
    l1 = gen_new_label();
3189 3190
    tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
A
aurel32 已提交
3191
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3192 3193 3194
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_reserve, -1);
    tcg_temp_free(t0);
J
j_mayer 已提交
3195 3196 3197
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3198
/* sync */
3199
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
B
bellard 已提交
3200 3201 3202
{
}

3203 3204 3205
/* wait */
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
{
3206 3207 3208
    TCGv_i32 t0 = tcg_temp_new_i32();
    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
    tcg_temp_free_i32(t0);
3209
    /* Stop translation, as the CPU is supposed to sleep from now */
A
aurel32 已提交
3210
    gen_exception_err(ctx, EXCP_HLT, 1);
3211 3212
}

B
bellard 已提交
3213
/***                         Floating-point load                           ***/
3214 3215
#define GEN_LDF(name, ldop, opc, type)                                        \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
B
bellard 已提交
3216
{                                                                             \
3217
    TCGv EA;                                                                  \
3218
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3219
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3220 3221
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3222
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3223
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3224 3225
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3226
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3227 3228
}

3229 3230
#define GEN_LDUF(name, ldop, opc, type)                                       \
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
B
bellard 已提交
3231
{                                                                             \
3232
    TCGv EA;                                                                  \
3233
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3234
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3235 3236
        return;                                                               \
    }                                                                         \
3237
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3238
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3239
        return;                                                               \
3240
    }                                                                         \
A
aurel32 已提交
3241
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3242
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3243 3244
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3245 3246
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3247 3248
}

3249 3250
#define GEN_LDUXF(name, ldop, opc, type)                                      \
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type)                      \
B
bellard 已提交
3251
{                                                                             \
3252
    TCGv EA;                                                                  \
3253
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3254
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3255 3256
        return;                                                               \
    }                                                                         \
3257
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3258
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3259
        return;                                                               \
3260
    }                                                                         \
A
aurel32 已提交
3261
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3262
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3263 3264
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3265 3266
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3267 3268
}

3269 3270
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
B
bellard 已提交
3271
{                                                                             \
3272
    TCGv EA;                                                                  \
3273
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3274
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3275 3276
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3277
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3278
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3279 3280
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3281
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3282 3283
}

3284 3285 3286 3287 3288 3289
#define GEN_LDFS(name, ldop, op, type)                                        \
GEN_LDF(name, ldop, op | 0x20, type);                                         \
GEN_LDUF(name, ldop, op | 0x21, type);                                        \
GEN_LDUXF(name, ldop, op | 0x01, type);                                       \
GEN_LDXF(name, ldop, 0x17, op | 0x00, type)

A
aurel32 已提交
3290
static always_inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3291 3292 3293
{
    TCGv t0 = tcg_temp_new();
    TCGv_i32 t1 = tcg_temp_new_i32();
A
aurel32 已提交
3294
    gen_qemu_ld32u(ctx, t0, arg2);
3295 3296 3297 3298 3299
    tcg_gen_trunc_tl_i32(t1, t0);
    tcg_temp_free(t0);
    gen_helper_float32_to_float64(arg1, t1);
    tcg_temp_free_i32(t1);
}
B
bellard 已提交
3300

3301 3302 3303 3304
 /* lfd lfdu lfdux lfdx */
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3305 3306

/***                         Floating-point store                          ***/
3307 3308
#define GEN_STF(name, stop, opc, type)                                        \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
B
bellard 已提交
3309
{                                                                             \
3310
    TCGv EA;                                                                  \
3311
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3312
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3313 3314
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3315
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3316
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3317 3318
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3319
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3320 3321
}

3322 3323
#define GEN_STUF(name, stop, opc, type)                                       \
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
B
bellard 已提交
3324
{                                                                             \
3325
    TCGv EA;                                                                  \
3326
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3327
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3328 3329
        return;                                                               \
    }                                                                         \
3330
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3331
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3332
        return;                                                               \
3333
    }                                                                         \
A
aurel32 已提交
3334
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3335
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3336 3337
    gen_addr_imm_index(ctx, EA, 0);                                           \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3338 3339
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3340 3341
}

3342 3343
#define GEN_STUXF(name, stop, opc, type)                                      \
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type)                      \
B
bellard 已提交
3344
{                                                                             \
3345
    TCGv EA;                                                                  \
3346
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3347
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3348 3349
        return;                                                               \
    }                                                                         \
3350
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
A
aurel32 已提交
3351
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3352
        return;                                                               \
3353
    }                                                                         \
A
aurel32 已提交
3354
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3355
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3356 3357
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3358 3359
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3360 3361
}

3362 3363
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
B
bellard 已提交
3364
{                                                                             \
3365
    TCGv EA;                                                                  \
3366
    if (unlikely(!ctx->fpu_enabled)) {                                        \
A
aurel32 已提交
3367
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3368 3369
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
3370
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3371
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
3372 3373
    gen_addr_reg_index(ctx, EA);                                              \
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3374
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
3375 3376
}

3377 3378 3379 3380 3381 3382
#define GEN_STFS(name, stop, op, type)                                        \
GEN_STF(name, stop, op | 0x20, type);                                         \
GEN_STUF(name, stop, op | 0x21, type);                                        \
GEN_STUXF(name, stop, op | 0x01, type);                                       \
GEN_STXF(name, stop, 0x17, op | 0x00, type)

A
aurel32 已提交
3383
static always_inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3384 3385 3386 3387 3388 3389
{
    TCGv_i32 t0 = tcg_temp_new_i32();
    TCGv t1 = tcg_temp_new();
    gen_helper_float64_to_float32(t0, arg1);
    tcg_gen_extu_i32_tl(t1, t0);
    tcg_temp_free_i32(t0);
A
aurel32 已提交
3390
    gen_qemu_st32(ctx, t1, arg2);
3391 3392
    tcg_temp_free(t1);
}
B
bellard 已提交
3393 3394

/* stfd stfdu stfdux stfdx */
3395
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
B
bellard 已提交
3396
/* stfs stfsu stfsux stfsx */
3397
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3398 3399

/* Optional: */
A
aurel32 已提交
3400
static always_inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3401 3402 3403
{
    TCGv t0 = tcg_temp_new();
    tcg_gen_trunc_i64_tl(t0, arg1),
A
aurel32 已提交
3404
    gen_qemu_st32(ctx, t0, arg2);
3405 3406
    tcg_temp_free(t0);
}
B
bellard 已提交
3407
/* stfiwx */
3408
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3409 3410

/***                                Branch                                 ***/
3411 3412
static always_inline void gen_goto_tb (DisasContext *ctx, int n,
                                       target_ulong dest)
3413 3414 3415
{
    TranslationBlock *tb;
    tb = ctx->tb;
3416 3417 3418 3419
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        dest = (uint32_t) dest;
#endif
B
bellard 已提交
3420
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3421
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3422
        tcg_gen_goto_tb(n);
3423
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
B
bellard 已提交
3424
        tcg_gen_exit_tb((long)tb + n);
3425
    } else {
3426
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3427 3428
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3429
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3430 3431 3432
                ctx->exception == POWERPC_EXCP_BRANCH) {
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
A
aurel32 已提交
3433
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3434 3435 3436
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
A
aurel32 已提交
3437
                gen_debug_exception(ctx);
3438 3439
            }
        }
B
bellard 已提交
3440
        tcg_gen_exit_tb(0);
3441
    }
B
bellard 已提交
3442 3443
}

3444
static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
3445 3446
{
#if defined(TARGET_PPC64)
3447 3448
    if (ctx->sf_mode == 0)
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3449 3450
    else
#endif
3451
        tcg_gen_movi_tl(cpu_lr, nip);
3452 3453
}

B
bellard 已提交
3454 3455 3456
/* b ba bl bla */
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
3457
    target_ulong li, target;
B
bellard 已提交
3458

3459
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3460
    /* sign extend LI */
3461
#if defined(TARGET_PPC64)
3462 3463 3464
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
3465
#endif
3466
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3467
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
3468
        target = ctx->nip + li - 4;
B
bellard 已提交
3469
    else
3470
        target = li;
3471 3472
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3473
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3474 3475
}

3476 3477 3478 3479
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

3480
static always_inline void gen_bcond (DisasContext *ctx, int type)
3481 3482
{
    uint32_t bo = BO(ctx->opcode);
3483 3484
    int l1 = gen_new_label();
    TCGv target;
3485

3486
    ctx->exception = POWERPC_EXCP_BRANCH;
3487
    if (type == BCOND_LR || type == BCOND_CTR) {
P
pbrook 已提交
3488
        target = tcg_temp_local_new();
3489 3490 3491 3492
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3493
    }
3494 3495
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3496 3497 3498
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
P
pbrook 已提交
3499
        TCGv temp = tcg_temp_new();
3500
        if (unlikely(type == BCOND_CTR)) {
A
aurel32 已提交
3501
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3502 3503 3504
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3505
#if defined(TARGET_PPC64)
3506 3507 3508
        if (!ctx->sf_mode)
            tcg_gen_ext32u_tl(temp, cpu_ctr);
        else
3509
#endif
3510 3511 3512 3513 3514
            tcg_gen_mov_tl(temp, cpu_ctr);
        if (bo & 0x2) {
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
        } else {
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3515
        }
P
pbrook 已提交
3516
        tcg_temp_free(temp);
3517 3518 3519 3520 3521
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
3522
        TCGv_i32 temp = tcg_temp_new_i32();
3523

3524
        if (bo & 0x8) {
3525 3526
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3527
        } else {
3528 3529
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3530
        }
P
pbrook 已提交
3531
        tcg_temp_free_i32(temp);
3532
    }
3533
    if (type == BCOND_IM) {
3534 3535 3536 3537 3538 3539
        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
        if (likely(AA(ctx->opcode) == 0)) {
            gen_goto_tb(ctx, 0, ctx->nip + li - 4);
        } else {
            gen_goto_tb(ctx, 0, li);
        }
B
bellard 已提交
3540
        gen_set_label(l1);
3541
        gen_goto_tb(ctx, 1, ctx->nip);
3542
    } else {
3543
#if defined(TARGET_PPC64)
3544 3545 3546 3547 3548 3549 3550 3551 3552 3553
        if (!(ctx->sf_mode))
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
        else
#endif
            tcg_gen_andi_tl(cpu_nip, target, ~3);
        tcg_gen_exit_tb(0);
        gen_set_label(l1);
#if defined(TARGET_PPC64)
        if (!(ctx->sf_mode))
            tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
3554 3555
        else
#endif
3556
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
B
bellard 已提交
3557
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3558
    }
3559 3560 3561
}

GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3562
{
3563 3564 3565 3566
    gen_bcond(ctx, BCOND_IM);
}

GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3567
{
3568 3569 3570 3571
    gen_bcond(ctx, BCOND_CTR);
}

GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3572
{
3573 3574
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3575 3576

/***                      Condition register logical                       ***/
3577 3578
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)                   \
B
bellard 已提交
3579
{                                                                             \
3580 3581
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
P
pbrook 已提交
3582
    TCGv_i32 t0, t1;                                                          \
3583
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
P
pbrook 已提交
3584
    t0 = tcg_temp_new_i32();                                                  \
3585
    if (sh > 0)                                                               \
3586
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3587
    else if (sh < 0)                                                          \
3588
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3589
    else                                                                      \
3590
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
P
pbrook 已提交
3591
    t1 = tcg_temp_new_i32();                                                  \
3592 3593
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3594
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3595
    else if (sh < 0)                                                          \
3596
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3597
    else                                                                      \
3598 3599
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3600
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3601 3602 3603
    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 已提交
3604 3605
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
B
bellard 已提交
3606 3607 3608
}

/* crand */
3609
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3610
/* crandc */
3611
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3612
/* creqv */
3613
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3614
/* crnand */
3615
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3616
/* crnor */
3617
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3618
/* cror */
3619
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3620
/* crorc */
3621
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3622
/* crxor */
3623
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
bellard 已提交
3624 3625 3626
/* mcrf */
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
{
A
aurel32 已提交
3627
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3628 3629 3630
}

/***                           System linkage                              ***/
A
aurel32 已提交
3631
/* rfi (mem_idx only) */
3632
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
B
bellard 已提交
3633
{
3634
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3635
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3636 3637
#else
    /* Restore CPU state */
A
aurel32 已提交
3638
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3639
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3640
        return;
3641
    }
3642
    gen_helper_rfi();
A
aurel32 已提交
3643
    gen_sync_exception(ctx);
3644
#endif
B
bellard 已提交
3645 3646
}

J
j_mayer 已提交
3647
#if defined(TARGET_PPC64)
3648
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
J
j_mayer 已提交
3649 3650
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3651
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3652 3653
#else
    /* Restore CPU state */
A
aurel32 已提交
3654
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3655
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
3656 3657
        return;
    }
3658
    gen_helper_rfid();
A
aurel32 已提交
3659
    gen_sync_exception(ctx);
J
j_mayer 已提交
3660 3661 3662
#endif
}

J
j_mayer 已提交
3663
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
3664 3665
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3666
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3667 3668
#else
    /* Restore CPU state */
A
aurel32 已提交
3669
    if (unlikely(ctx->mem_idx <= 1)) {
A
aurel32 已提交
3670
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3671 3672
        return;
    }
3673
    gen_helper_hrfid();
A
aurel32 已提交
3674
    gen_sync_exception(ctx);
3675 3676 3677 3678
#endif
}
#endif

B
bellard 已提交
3679
/* sc */
3680 3681 3682 3683 3684
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
3685
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
B
bellard 已提交
3686
{
3687 3688 3689
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
A
aurel32 已提交
3690
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3691 3692 3693 3694
}

/***                                Trap                                   ***/
/* tw */
3695
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
B
bellard 已提交
3696
{
3697
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3698
    /* Update the nip since this might generate a trap exception */
3699
    gen_update_nip(ctx, ctx->nip);
3700 3701
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
B
bellard 已提交
3702 3703 3704 3705 3706
}

/* twi */
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
3707 3708
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3709 3710
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3711 3712 3713
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
B
bellard 已提交
3714 3715
}

3716 3717 3718 3719
#if defined(TARGET_PPC64)
/* td */
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
{
3720
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3721 3722
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3723 3724
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
3725 3726 3727 3728 3729
}

/* tdi */
GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
{
3730 3731
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3732 3733
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3734 3735 3736
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free_i32(t1);
3737 3738 3739
}
#endif

B
bellard 已提交
3740 3741 3742 3743
/***                          Processor control                            ***/
/* mcrxr */
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
{
A
aurel32 已提交
3744 3745
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3746
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
B
bellard 已提交
3747 3748
}

A
aurel32 已提交
3749
/* mfcr mfocrf */
3750
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
B
bellard 已提交
3751
{
3752
    uint32_t crm, crn;
3753

3754 3755
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
M
malc 已提交
3756
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
A
aurel32 已提交
3757
            crn = ctz32 (crm);
3758
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
A
aurel32 已提交
3759 3760
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3761
        }
3762
    } else {
A
aurel32 已提交
3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780
        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);
3781
    }
B
bellard 已提交
3782 3783 3784 3785 3786
}

/* mfmsr */
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
{
3787
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3788
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3789
#else
A
aurel32 已提交
3790
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3791
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3792
        return;
3793
    }
3794
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3795
#endif
B
bellard 已提交
3796 3797
}

J
j_mayer 已提交
3798
#if 1
3799
#define SPR_NOACCESS ((void *)(-1UL))
3800 3801 3802 3803 3804 3805 3806 3807 3808
#else
static void spr_noaccess (void *opaque, int sprn)
{
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
    printf("ERROR: try to access SPR %d !\n", sprn);
}
#define SPR_NOACCESS (&spr_noaccess)
#endif

B
bellard 已提交
3809
/* mfspr */
3810
static always_inline void gen_op_mfspr (DisasContext *ctx)
B
bellard 已提交
3811
{
A
aurel32 已提交
3812
    void (*read_cb)(void *opaque, int gprn, int sprn);
B
bellard 已提交
3813 3814
    uint32_t sprn = SPR(ctx->opcode);

3815
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3816
    if (ctx->mem_idx == 2)
3817
        read_cb = ctx->spr_cb[sprn].hea_read;
A
aurel32 已提交
3818
    else if (ctx->mem_idx)
3819 3820
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3821
#endif
3822
        read_cb = ctx->spr_cb[sprn].uea_read;
3823 3824
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3825
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3826 3827
        } else {
            /* Privilege exception */
3828 3829 3830 3831 3832
            /* 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) {
3833
                qemu_log("Trying to read privileged spr %d %03x at "
J
j_mayer 已提交
3834 3835 3836
                            ADDRX "\n", sprn, sprn, ctx->nip);
                printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
                       sprn, sprn, ctx->nip);
3837
            }
A
aurel32 已提交
3838
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
B
bellard 已提交
3839
        }
3840 3841
    } else {
        /* Not defined */
3842
        qemu_log("Trying to read invalid spr %d %03x at "
J
j_mayer 已提交
3843 3844 3845
                    ADDRX "\n", sprn, sprn, ctx->nip);
        printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3846
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3847 3848 3849
    }
}

3850
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
B
bellard 已提交
3851
{
3852
    gen_op_mfspr(ctx);
3853
}
3854 3855

/* mftb */
3856
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3857 3858
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3859 3860
}

A
aurel32 已提交
3861
/* mtcrf mtocrf*/
3862
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
B
bellard 已提交
3863
{
3864
    uint32_t crm, crn;
3865

3866
    crm = CRM(ctx->opcode);
M
malc 已提交
3867 3868 3869
    if (likely((ctx->opcode & 0x00100000))) {
        if (crm && ((crm & (crm - 1)) == 0)) {
            TCGv_i32 temp = tcg_temp_new_i32();
A
aurel32 已提交
3870
            crn = ctz32 (crm);
M
malc 已提交
3871
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
A
aurel32 已提交
3872 3873
            tcg_gen_shri_i32(temp, temp, crn * 4);
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
M
malc 已提交
3874 3875
            tcg_temp_free_i32(temp);
        }
3876
    } else {
A
aurel32 已提交
3877 3878 3879 3880 3881 3882 3883 3884
        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 已提交
3885
        tcg_temp_free_i32(temp);
3886
    }
B
bellard 已提交
3887 3888 3889
}

/* mtmsr */
J
j_mayer 已提交
3890
#if defined(TARGET_PPC64)
3891
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
J
j_mayer 已提交
3892 3893
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3894
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3895
#else
A
aurel32 已提交
3896
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3897
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
J
j_mayer 已提交
3898 3899
        return;
    }
3900 3901
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3902 3903 3904 3905 3906
        TCGv t0 = tcg_temp_new();
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
        tcg_temp_free(t0);
3907
    } else {
3908 3909 3910 3911
        /* 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
         */
3912
        gen_update_nip(ctx, ctx->nip);
3913
        gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3914 3915
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3916
        gen_stop_exception(ctx);
3917
    }
J
j_mayer 已提交
3918 3919 3920 3921
#endif
}
#endif

B
bellard 已提交
3922 3923
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
{
3924
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3925
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3926
#else
A
aurel32 已提交
3927
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
3928
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3929
        return;
3930
    }
3931 3932
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
3933 3934 3935 3936 3937
        TCGv t0 = tcg_temp_new();
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
        tcg_temp_free(t0);
3938
    } else {
3939 3940 3941 3942
        /* 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
         */
3943
        gen_update_nip(ctx, ctx->nip);
3944
#if defined(TARGET_PPC64)
3945 3946 3947 3948 3949 3950 3951 3952 3953 3954
        if (!ctx->sf_mode) {
            TCGv t0 = tcg_temp_new();
            TCGv t1 = tcg_temp_new();
            tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
            tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
            tcg_gen_or_tl(t0, t0, t1);
            tcg_temp_free(t1);
            gen_helper_store_msr(t0);
            tcg_temp_free(t0);
        } else
3955
#endif
3956
            gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3957
        /* Must stop the translation as machine state (may have) changed */
3958
        /* Note that mtmsr is not always defined as context-synchronizing */
A
aurel32 已提交
3959
        gen_stop_exception(ctx);
3960
    }
3961
#endif
B
bellard 已提交
3962 3963 3964 3965 3966
}

/* mtspr */
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
{
A
aurel32 已提交
3967
    void (*write_cb)(void *opaque, int sprn, int gprn);
B
bellard 已提交
3968 3969
    uint32_t sprn = SPR(ctx->opcode);

3970
#if !defined(CONFIG_USER_ONLY)
A
aurel32 已提交
3971
    if (ctx->mem_idx == 2)
3972
        write_cb = ctx->spr_cb[sprn].hea_write;
A
aurel32 已提交
3973
    else if (ctx->mem_idx)
3974 3975
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
3976
#endif
3977
        write_cb = ctx->spr_cb[sprn].uea_write;
3978 3979
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3980
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
3981 3982
        } else {
            /* Privilege exception */
3983
            qemu_log("Trying to write privileged spr %d %03x at "
J
j_mayer 已提交
3984 3985 3986
                        ADDRX "\n", sprn, sprn, ctx->nip);
            printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
                   sprn, sprn, ctx->nip);
A
aurel32 已提交
3987
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3988
        }
3989 3990
    } else {
        /* Not defined */
3991
        qemu_log("Trying to write invalid spr %d %03x at "
J
j_mayer 已提交
3992 3993 3994
                    ADDRX "\n", sprn, sprn, ctx->nip);
        printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
               sprn, sprn, ctx->nip);
A
aurel32 已提交
3995
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3996 3997 3998 3999 4000
    }
}

/***                         Cache management                              ***/
/* dcbf */
4001
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
B
bellard 已提交
4002
{
J
j_mayer 已提交
4003
    /* XXX: specification says this is treated as a load by the MMU */
A
aurel32 已提交
4004 4005 4006 4007 4008
    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);
4009
    tcg_temp_free(t0);
B
bellard 已提交
4010 4011 4012
}

/* dcbi (Supervisor only) */
4013
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
B
bellard 已提交
4014
{
4015
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4016
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4017
#else
A
aurel32 已提交
4018
    TCGv EA, val;
A
aurel32 已提交
4019
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4020
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4021
        return;
4022
    }
P
pbrook 已提交
4023
    EA = tcg_temp_new();
A
aurel32 已提交
4024 4025
    gen_set_access_type(ctx, ACCESS_CACHE);
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
4026
    val = tcg_temp_new();
4027
    /* XXX: specification says this should be treated as a store by the MMU */
A
aurel32 已提交
4028 4029
    gen_qemu_ld8u(ctx, val, EA);
    gen_qemu_st8(ctx, val, EA);
A
aurel32 已提交
4030 4031
    tcg_temp_free(val);
    tcg_temp_free(EA);
4032
#endif
B
bellard 已提交
4033 4034 4035
}

/* dcdst */
4036
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
B
bellard 已提交
4037
{
4038
    /* XXX: specification say this is treated as a load by the MMU */
A
aurel32 已提交
4039 4040 4041 4042 4043
    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);
4044
    tcg_temp_free(t0);
B
bellard 已提交
4045 4046 4047
}

/* dcbt */
4048
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
B
bellard 已提交
4049
{
4050
    /* interpreted as no-op */
4051 4052 4053
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4054 4055 4056
}

/* dcbtst */
4057
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
B
bellard 已提交
4058
{
4059
    /* interpreted as no-op */
4060 4061 4062
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4063 4064 4065
}

/* dcbz */
4066
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
B
bellard 已提交
4067
{
A
aurel32 已提交
4068 4069
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4070 4071
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4072 4073
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4074 4075
    gen_helper_dcbz(t0);
    tcg_temp_free(t0);
4076 4077
}

4078
GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
4079
{
A
aurel32 已提交
4080 4081
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4082 4083
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4084 4085
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4086
    if (ctx->opcode & 0x00200000)
4087
        gen_helper_dcbz(t0);
4088
    else
4089 4090
        gen_helper_dcbz_970(t0);
    tcg_temp_free(t0);
B
bellard 已提交
4091 4092
}

4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119
/* dst / dstt */
GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC)
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }
}

/* dstst /dststt */
GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC)
{
    if (rA(ctx->opcode) == 0) {
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
    } else {
        /* interpreted as no-op */
    }

}

/* dss / dssall */
GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC)
{
    /* interpreted as no-op */
}

B
bellard 已提交
4120
/* icbi */
4121
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
B
bellard 已提交
4122
{
A
aurel32 已提交
4123 4124
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_CACHE);
4125 4126
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4127 4128
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4129 4130
    gen_helper_icbi(t0);
    tcg_temp_free(t0);
B
bellard 已提交
4131 4132 4133 4134
}

/* Optional: */
/* dcba */
4135
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
B
bellard 已提交
4136
{
4137 4138 4139 4140
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4141 4142 4143 4144 4145 4146 4147
}

/***                    Segment register manipulation                      ***/
/* Supervisor only: */
/* mfsr */
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
{
4148
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4149
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4150
#else
4151
    TCGv t0;
A
aurel32 已提交
4152
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4153
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4154
        return;
4155
    }
4156 4157 4158
    t0 = tcg_const_tl(SR(ctx->opcode));
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
4159
#endif
B
bellard 已提交
4160 4161 4162
}

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

/* mtsr */
B
bellard 已提交
4182
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
B
bellard 已提交
4183
{
4184
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4185
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4186
#else
4187
    TCGv t0;
A
aurel32 已提交
4188
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4189
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4190
        return;
4191
    }
4192 4193 4194
    t0 = tcg_const_tl(SR(ctx->opcode));
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
    tcg_temp_free(t0);
4195
#endif
B
bellard 已提交
4196 4197 4198
}

/* mtsrin */
4199
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
B
bellard 已提交
4200
{
4201
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4202
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4203
#else
4204
    TCGv t0;
A
aurel32 已提交
4205
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4206
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4207
        return;
4208
    }
4209 4210 4211 4212 4213
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
    gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
    tcg_temp_free(t0);
4214
#endif
B
bellard 已提交
4215 4216
}

4217 4218 4219
#if defined(TARGET_PPC64)
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
/* mfsr */
4220
GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
4221 4222
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4223
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4224
#else
4225
    TCGv t0;
A
aurel32 已提交
4226
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4227
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4228 4229
        return;
    }
4230
    t0 = tcg_const_tl(SR(ctx->opcode));
B
blueswir1 已提交
4231
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4232
    tcg_temp_free(t0);
4233 4234 4235 4236
#endif
}

/* mfsrin */
4237 4238
GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
             PPC_SEGMENT_64B)
4239 4240
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4241
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4242
#else
4243
    TCGv t0;
A
aurel32 已提交
4244
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4245
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4246 4247
        return;
    }
4248 4249 4250
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
B
blueswir1 已提交
4251
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4252
    tcg_temp_free(t0);
4253 4254 4255 4256
#endif
}

/* mtsr */
4257
GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
4258 4259
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4260
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4261
#else
4262
    TCGv t0;
A
aurel32 已提交
4263
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4264
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4265 4266
        return;
    }
4267
    t0 = tcg_const_tl(SR(ctx->opcode));
B
blueswir1 已提交
4268
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4269
    tcg_temp_free(t0);
4270 4271 4272 4273
#endif
}

/* mtsrin */
4274 4275
GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
             PPC_SEGMENT_64B)
4276 4277
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4278
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4279
#else
4280
    TCGv t0;
A
aurel32 已提交
4281
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4282
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4283 4284
        return;
    }
4285 4286 4287
    t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
B
blueswir1 已提交
4288
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4289
    tcg_temp_free(t0);
4290 4291
#endif
}
B
blueswir1 已提交
4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306

/* slbmte */
GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
        return;
    }
    gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
#endif
}

4307 4308
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4309
/***                      Lookaside buffer management                      ***/
A
aurel32 已提交
4310
/* Optional & mem_idx only: */
B
bellard 已提交
4311
/* tlbia */
4312
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
B
bellard 已提交
4313
{
4314
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4315
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4316
#else
A
aurel32 已提交
4317
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4318
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4319
        return;
4320
    }
4321
    gen_helper_tlbia();
4322
#endif
B
bellard 已提交
4323 4324
}

B
blueswir1 已提交
4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338
/* tlbiel */
GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE)
{
#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
    if (unlikely(!ctx->mem_idx)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return;
    }
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
#endif
}

B
bellard 已提交
4339
/* tlbie */
4340
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
B
bellard 已提交
4341
{
4342
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4343
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4344
#else
A
aurel32 已提交
4345
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4346
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4347
        return;
4348
    }
4349
#if defined(TARGET_PPC64)
4350 4351 4352 4353 4354 4355
    if (!ctx->sf_mode) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
        gen_helper_tlbie(t0);
        tcg_temp_free(t0);
    } else
4356
#endif
4357
        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4358
#endif
B
bellard 已提交
4359 4360 4361
}

/* tlbsync */
4362
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
B
bellard 已提交
4363
{
4364
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4365
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4366
#else
A
aurel32 已提交
4367
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4368
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4369
        return;
4370 4371 4372 4373
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
A
aurel32 已提交
4374
    gen_stop_exception(ctx);
4375
#endif
B
bellard 已提交
4376 4377
}

J
j_mayer 已提交
4378 4379 4380 4381 4382
#if defined(TARGET_PPC64)
/* slbia */
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4383
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4384
#else
A
aurel32 已提交
4385
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4386
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4387 4388
        return;
    }
4389
    gen_helper_slbia();
J
j_mayer 已提交
4390 4391 4392 4393 4394 4395 4396
#endif
}

/* slbie */
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
4397
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4398
#else
A
aurel32 已提交
4399
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
4400
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
J
j_mayer 已提交
4401 4402
        return;
    }
4403
    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
4404 4405 4406 4407
#endif
}
#endif

B
bellard 已提交
4408 4409
/***                              External control                         ***/
/* Optional: */
4410
/* eciwx */
B
bellard 已提交
4411 4412
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
{
A
aurel32 已提交
4413
    TCGv t0;
4414
    /* Should check EAR[E] ! */
A
aurel32 已提交
4415 4416 4417
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4418
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4419
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4420
    tcg_temp_free(t0);
4421 4422 4423 4424 4425
}

/* ecowx */
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
{
A
aurel32 已提交
4426
    TCGv t0;
4427
    /* Should check EAR[E] ! */
A
aurel32 已提交
4428 4429 4430
    gen_set_access_type(ctx, ACCESS_EXT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
4431
    gen_check_align(ctx, t0, 0x03);
A
aurel32 已提交
4432
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4433
    tcg_temp_free(t0);
4434 4435 4436 4437 4438 4439
}

/* PowerPC 601 specific instructions */
/* abs - abs. */
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
{
4440 4441 4442 4443 4444 4445 4446 4447
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l2);
4448
    if (unlikely(Rc(ctx->opcode) != 0))
4449
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4450 4451 4452 4453 4454
}

/* abso - abso. */
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
{
4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l3);
    gen_set_label(l2);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l3);
4470
    if (unlikely(Rc(ctx->opcode) != 0))
4471
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4472 4473 4474
}

/* clcs */
4475
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
4476
{
4477 4478 4479
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
4480
    /* Rc=1 sets CR0 to an undefined state */
4481 4482 4483 4484 4485
}

/* div - div. */
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
{
4486
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4487
    if (unlikely(Rc(ctx->opcode) != 0))
4488
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4489 4490 4491 4492 4493
}

/* divo - divo. */
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
{
4494
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4495
    if (unlikely(Rc(ctx->opcode) != 0))
4496
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4497 4498 4499 4500 4501
}

/* divs - divs. */
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
{
4502
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4503
    if (unlikely(Rc(ctx->opcode) != 0))
4504
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4505 4506 4507 4508 4509
}

/* divso - divso. */
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
{
4510
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4511
    if (unlikely(Rc(ctx->opcode) != 0))
4512
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4513 4514 4515 4516 4517
}

/* doz - doz. */
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
{
4518 4519 4520 4521 4522 4523 4524 4525
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
    tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    gen_set_label(l2);
4526
    if (unlikely(Rc(ctx->opcode) != 0))
4527
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4528 4529 4530 4531 4532
}

/* dozo - dozo. */
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
{
4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
    tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
    tcg_gen_andc_tl(t1, t1, t2);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    gen_set_label(l2);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4555
    if (unlikely(Rc(ctx->opcode) != 0))
4556
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4557 4558 4559 4560 4561
}

/* dozi */
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
{
4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572
    target_long simm = SIMM(ctx->opcode);
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
    tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    gen_set_label(l2);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4573 4574 4575 4576 4577
}

/* lscbx - lscbx. */
GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
{
4578 4579 4580 4581
    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));
4582

A
aurel32 已提交
4583
    gen_addr_reg_index(ctx, t0);
4584
    /* NIP cannot be restored if the memory exception comes from an helper */
4585
    gen_update_nip(ctx, ctx->nip - 4);
4586 4587 4588 4589
    gen_helper_lscbx(t0, t0, t1, t2, t3);
    tcg_temp_free_i32(t1);
    tcg_temp_free_i32(t2);
    tcg_temp_free_i32(t3);
A
aurel32 已提交
4590
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4591
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4592
    if (unlikely(Rc(ctx->opcode) != 0))
4593 4594
        gen_set_Rc0(ctx, t0);
    tcg_temp_free(t0);
4595 4596 4597 4598 4599
}

/* maskg - maskg. */
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
{
4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    TCGv t3 = tcg_temp_new();
    tcg_gen_movi_tl(t3, 0xFFFFFFFF);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
    tcg_gen_addi_tl(t2, t0, 1);
    tcg_gen_shr_tl(t2, t3, t2);
    tcg_gen_shr_tl(t3, t3, t1);
    tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
    tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
    tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
    tcg_temp_free(t3);
4619
    if (unlikely(Rc(ctx->opcode) != 0))
4620
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4621 4622 4623 4624 4625
}

/* maskir - maskir. */
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
{
4626 4627 4628 4629 4630 4631 4632
    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);
4633
    if (unlikely(Rc(ctx->opcode) != 0))
4634
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4635 4636 4637 4638 4639
}

/* mul - mul. */
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
{
4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652
    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);
4653
    if (unlikely(Rc(ctx->opcode) != 0))
4654
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4655 4656 4657 4658 4659
}

/* mulo - mulo. */
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
{
4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679
    int l1 = gen_new_label();
    TCGv_i64 t0 = tcg_temp_new_i64();
    TCGv_i64 t1 = tcg_temp_new_i64();
    TCGv t2 = tcg_temp_new();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_trunc_i64_tl(t2, t0);
    gen_store_spr(SPR_MQ, t2);
    tcg_gen_shri_i64(t1, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
    tcg_gen_ext32s_i64(t1, t0);
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    gen_set_label(l1);
    tcg_temp_free_i64(t0);
    tcg_temp_free_i64(t1);
    tcg_temp_free(t2);
4680
    if (unlikely(Rc(ctx->opcode) != 0))
4681
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4682 4683 4684 4685 4686
}

/* nabs - nabs. */
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
{
4687 4688 4689 4690 4691 4692 4693 4694
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l2);
4695
    if (unlikely(Rc(ctx->opcode) != 0))
4696
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4697 4698 4699 4700 4701
}

/* nabso - nabso. */
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
{
4702 4703 4704 4705 4706 4707 4708 4709 4710 4711
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    gen_set_label(l2);
    /* nabs never overflows */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4712
    if (unlikely(Rc(ctx->opcode) != 0))
4713
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4714 4715 4716 4717 4718
}

/* rlmi - rlmi. */
GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
{
4719 4720 4721 4722 4723 4724 4725 4726 4727
    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);
4728
    if (unlikely(Rc(ctx->opcode) != 0))
4729
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4730 4731 4732 4733 4734
}

/* rrib - rrib. */
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
{
4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745
    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);
4746
    if (unlikely(Rc(ctx->opcode) != 0))
4747
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4748 4749 4750 4751 4752
}

/* sle - sle. */
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
{
4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763
    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);
4764
    if (unlikely(Rc(ctx->opcode) != 0))
4765
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4766 4767 4768 4769 4770
}

/* sleq - sleq. */
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
{
4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785
    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);
4786
    if (unlikely(Rc(ctx->opcode) != 0))
4787
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4788 4789 4790 4791 4792
}

/* sliq - sliq. */
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
{
4793 4794 4795 4796 4797 4798 4799 4800 4801 4802
    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);
4803
    if (unlikely(Rc(ctx->opcode) != 0))
4804
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4805 4806 4807 4808 4809
}

/* slliq - slliq. */
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
{
4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820
    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);
4821
    if (unlikely(Rc(ctx->opcode) != 0))
4822
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4823 4824 4825 4826 4827
}

/* sllq - sllq. */
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
{
4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    TCGv t0 = tcg_temp_local_new();
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
    tcg_gen_shl_tl(t1, t1, t2);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
    gen_load_spr(t0, SPR_MQ);
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
    gen_load_spr(t2, SPR_MQ);
    tcg_gen_andc_tl(t1, t2, t1);
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    gen_set_label(l2);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4850
    if (unlikely(Rc(ctx->opcode) != 0))
4851
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4852 4853 4854 4855 4856
}

/* slq - slq. */
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
{
4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_subfi_tl(t1, 32, t1);
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_or_tl(t1, t0, t1);
    gen_store_spr(SPR_MQ, t1);
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    gen_set_label(l1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4873
    if (unlikely(Rc(ctx->opcode) != 0))
4874
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4875 4876
}

4877
/* sraiq - sraiq. */
4878 4879
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
{
4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895
    int sh = SH(ctx->opcode);
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
    tcg_gen_or_tl(t0, t0, t1);
    gen_store_spr(SPR_MQ, t0);
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
    gen_set_label(l1);
    tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
4896
    if (unlikely(Rc(ctx->opcode) != 0))
4897
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4898 4899 4900 4901 4902
}

/* sraq - sraq. */
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
{
4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
    tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
    tcg_gen_subfi_tl(t2, 32, t2);
    tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
    tcg_gen_or_tl(t0, t0, t2);
    gen_store_spr(SPR_MQ, t0);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
    tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
    gen_set_label(l1);
    tcg_temp_free(t0);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
    gen_set_label(l2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
4929
    if (unlikely(Rc(ctx->opcode) != 0))
4930
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4931 4932 4933 4934 4935
}

/* sre - sre. */
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
{
4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946
    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);
4947
    if (unlikely(Rc(ctx->opcode) != 0))
4948
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4949 4950 4951 4952 4953
}

/* srea - srea. */
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
{
4954 4955 4956 4957 4958 4959 4960 4961
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_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);
4962
    if (unlikely(Rc(ctx->opcode) != 0))
4963
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4964 4965 4966 4967 4968
}

/* sreq */
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
{
4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    TCGv t2 = tcg_temp_new();
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_movi_tl(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);
4984
    if (unlikely(Rc(ctx->opcode) != 0))
4985
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4986 4987 4988 4989 4990
}

/* sriq */
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
{
4991 4992 4993 4994 4995 4996 4997 4998 4999 5000
    int sh = SH(ctx->opcode);
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_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);
5001
    if (unlikely(Rc(ctx->opcode) != 0))
5002
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5003 5004 5005 5006 5007
}

/* srliq */
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
{
5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018
    int sh = SH(ctx->opcode);
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_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);
5019
    if (unlikely(Rc(ctx->opcode) != 0))
5020
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5021 5022 5023 5024 5025
}

/* srlq */
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
{
5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    TCGv t0 = tcg_temp_local_new();
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
    tcg_gen_shr_tl(t2, t1, t2);
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
    gen_load_spr(t0, SPR_MQ);
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
    tcg_gen_and_tl(t0, t0, t2);
    gen_load_spr(t1, SPR_MQ);
    tcg_gen_andc_tl(t1, t1, t2);
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
    gen_set_label(l2);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
5049
    if (unlikely(Rc(ctx->opcode) != 0))
5050
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5051 5052 5053 5054 5055
}

/* srq */
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
{
5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071
    int l1 = gen_new_label();
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_subfi_tl(t1, 32, t1);
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
    tcg_gen_or_tl(t1, t0, t1);
    gen_store_spr(SPR_MQ, t1);
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    gen_set_label(l1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5072
    if (unlikely(Rc(ctx->opcode) != 0))
5073
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5074 5075 5076 5077 5078 5079 5080
}

/* PowerPC 602 specific instructions */
/* dsa  */
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
A
aurel32 已提交
5081
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5082 5083 5084 5085 5086 5087
}

/* esa */
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
A
aurel32 已提交
5088
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5089 5090 5091 5092 5093 5094
}

/* mfrom */
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5095
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5096
#else
A
aurel32 已提交
5097
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5098
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5099 5100
        return;
    }
5101
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5102 5103 5104 5105 5106
#endif
}

/* 602 - 603 - G2 TLB management */
/* tlbld */
5107
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
5108 5109
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5110
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5111
#else
A
aurel32 已提交
5112
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5113
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5114 5115
        return;
    }
5116
    gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5117 5118 5119 5120
#endif
}

/* tlbli */
5121
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
5122 5123
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5124
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5125
#else
A
aurel32 已提交
5126
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5127
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5128 5129
        return;
    }
5130
    gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5131 5132 5133
#endif
}

5134 5135
/* 74xx TLB management */
/* tlbld */
5136
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
5137 5138
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5139
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5140
#else
A
aurel32 已提交
5141
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5142
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5143 5144
        return;
    }
5145
    gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5146 5147 5148 5149
#endif
}

/* tlbli */
5150
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
5151 5152
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5153
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5154
#else
A
aurel32 已提交
5155
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5156
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5157 5158
        return;
    }
5159
    gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5160 5161 5162
#endif
}

5163 5164 5165 5166 5167 5168 5169 5170 5171 5172
/* POWER instructions not in PowerPC 601 */
/* clf */
GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
{
    /* Cache line flush: implemented as no-op */
}

/* cli */
GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
{
B
blueswir1 已提交
5173
    /* Cache line invalidate: privileged and treated as no-op */
5174
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5175
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5176
#else
A
aurel32 已提交
5177
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5178
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192
        return;
    }
#endif
}

/* dclst */
GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
{
    /* Data cache line store: treated as no-op */
}

GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5193
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5194
#else
5195 5196 5197
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);
    TCGv t0;
A
aurel32 已提交
5198
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5199
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5200 5201
        return;
    }
5202
    t0 = tcg_temp_new();
A
aurel32 已提交
5203
    gen_addr_reg_index(ctx, t0);
5204 5205 5206 5207
    tcg_gen_shri_tl(t0, t0, 28);
    tcg_gen_andi_tl(t0, t0, 0xF);
    gen_helper_load_sr(cpu_gpr[rd], t0);
    tcg_temp_free(t0);
5208
    if (ra != 0 && ra != rd)
5209
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5210 5211 5212 5213 5214 5215
#endif
}

GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5216
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5217
#else
5218
    TCGv t0;
A
aurel32 已提交
5219
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5220
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5221 5222
        return;
    }
5223
    t0 = tcg_temp_new();
A
aurel32 已提交
5224
    gen_addr_reg_index(ctx, t0);
5225 5226
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
5227 5228 5229 5230 5231 5232
#endif
}

GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5233
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5234
#else
A
aurel32 已提交
5235
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5236
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5237 5238
        return;
    }
5239
    gen_helper_rfsvc();
A
aurel32 已提交
5240
    gen_sync_exception(ctx);
5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251
#endif
}

/* svc is not implemented for now */

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

/* lfq */
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
5252
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5253 5254 5255 5256 5257 5258 5259
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_imm_index(ctx, t0, 0);
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t0, t0, 8);
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5260
    tcg_temp_free(t0);
5261 5262 5263 5264 5265 5266
}

/* lfqu */
GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    int ra = rA(ctx->opcode);
5267
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5268 5269 5270 5271 5272 5273 5274 5275
    TCGv t0, t1;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    t1 = tcg_temp_new();
    gen_addr_imm_index(ctx, t0, 0);
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t1, t0, 8);
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5276
    if (ra != 0)
5277 5278 5279
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5280 5281 5282 5283 5284 5285
}

/* lfqux */
GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
{
    int ra = rA(ctx->opcode);
5286
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5287 5288 5289 5290 5291 5292 5293 5294 5295
    gen_set_access_type(ctx, ACCESS_FLOAT);
    TCGv t0, t1;
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
    t1 = tcg_temp_new();
    gen_addr_add(ctx, t1, t0, 8);
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
    tcg_temp_free(t1);
5296
    if (ra != 0)
5297 5298
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5299 5300 5301 5302 5303
}

/* lfqx */
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
{
5304
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5305 5306 5307 5308 5309 5310 5311
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t0, t0, 8);
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5312
    tcg_temp_free(t0);
5313 5314 5315 5316 5317
}

/* stfq */
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
5318
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5319 5320 5321 5322 5323 5324 5325
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_imm_index(ctx, t0, 0);
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t0, t0, 8);
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5326
    tcg_temp_free(t0);
5327 5328 5329 5330 5331 5332
}

/* stfqu */
GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    int ra = rA(ctx->opcode);
5333
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5334 5335 5336 5337 5338 5339 5340 5341 5342
    TCGv t0, t1;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_imm_index(ctx, t0, 0);
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
    t1 = tcg_temp_new();
    gen_addr_add(ctx, t1, t0, 8);
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
    tcg_temp_free(t1);
5343
    if (ra != 0)
5344 5345
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5346 5347 5348 5349 5350 5351
}

/* stfqux */
GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
{
    int ra = rA(ctx->opcode);
5352
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5353 5354 5355 5356 5357 5358 5359 5360 5361
    TCGv t0, t1;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
    t1 = tcg_temp_new();
    gen_addr_add(ctx, t1, t0, 8);
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
    tcg_temp_free(t1);
5362
    if (ra != 0)
5363 5364
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
    tcg_temp_free(t0);
5365 5366 5367 5368 5369
}

/* stfqx */
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
{
5370
    int rd = rD(ctx->opcode);
A
aurel32 已提交
5371 5372 5373 5374 5375 5376 5377
    TCGv t0;
    gen_set_access_type(ctx, ACCESS_FLOAT);
    t0 = tcg_temp_new();
    gen_addr_reg_index(ctx, t0);
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
    gen_addr_add(ctx, t0, t0, 8);
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5378
    tcg_temp_free(t0);
5379 5380 5381
}

/* BookE specific instructions */
5382
/* XXX: not implemented on 440 ? */
5383
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
5384 5385
{
    /* XXX: TODO */
A
aurel32 已提交
5386
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5387 5388
}

5389
/* XXX: not implemented on 440 ? */
5390
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
5391 5392
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5393
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5394
#else
5395
    TCGv t0;
A
aurel32 已提交
5396
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5397
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5398 5399
        return;
    }
5400
    t0 = tcg_temp_new();
A
aurel32 已提交
5401
    gen_addr_reg_index(ctx, t0);
5402 5403
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
    tcg_temp_free(t0);
5404 5405 5406 5407
#endif
}

/* All 405 MAC instructions are translated here */
5408 5409 5410
static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
                                                int opc2, int opc3,
                                                int ra, int rb, int rt, int Rc)
5411
{
5412 5413
    TCGv t0, t1;

P
pbrook 已提交
5414 5415
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5416

5417 5418 5419 5420 5421 5422 5423
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5424 5425 5426
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5427 5428 5429 5430 5431
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5432 5433 5434
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5435 5436 5437 5438 5439 5440 5441
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5442 5443 5444 5445
        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);
5446 5447 5448 5449 5450
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5451 5452 5453 5454
        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);
5455 5456 5457 5458 5459 5460 5461
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5462 5463
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5464 5465 5466 5467 5468
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5469 5470
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5471 5472 5473
        break;
    }
    if (opc2 & 0x04) {
5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497
        /* (n)multiply-and-accumulate (0x0C / 0x0E) */
        tcg_gen_mul_tl(t1, t0, t1);
        if (opc2 & 0x02) {
            /* nmultiply-and-accumulate (0x0E) */
            tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
        } else {
            /* multiply-and-accumulate (0x0C) */
            tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
        }

        if (opc3 & 0x12) {
            /* Check overflow and/or saturate */
            int l1 = gen_new_label();

            if (opc3 & 0x10) {
                /* Start with XER OV disabled, the most likely case */
                tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
            }
            if (opc3 & 0x01) {
                /* Signed */
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
A
aurel32 已提交
5498
                if (opc3 & 0x02) {
5499 5500 5501 5502 5503 5504 5505
                    /* 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 已提交
5506
                if (opc3 & 0x02) {
5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519
                    /* Saturate */
                    tcg_gen_movi_tl(t0, UINT32_MAX);
                }
            }
            if (opc3 & 0x10) {
                /* Check overflow */
                tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
            }
            gen_set_label(l1);
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
        }
    } else {
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5520
    }
5521 5522
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5523 5524
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5525
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5526 5527 5528
    }
}

5529 5530
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)                  \
5531 5532 5533 5534 5535 5536
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5537
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5538
/* macchwo   - macchwo.   */
5539
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5540
/* macchws   - macchws.   */
5541
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5542
/* macchwso  - macchwso.  */
5543
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5544
/* macchwsu  - macchwsu.  */
5545
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5546
/* macchwsuo - macchwsuo. */
5547
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5548
/* macchwu   - macchwu.   */
5549
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5550
/* macchwuo  - macchwuo.  */
5551
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5552
/* machhw    - machhw.    */
5553
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5554
/* machhwo   - machhwo.   */
5555
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5556
/* machhws   - machhws.   */
5557
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5558
/* machhwso  - machhwso.  */
5559
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5560
/* machhwsu  - machhwsu.  */
5561
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5562
/* machhwsuo - machhwsuo. */
5563
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5564
/* machhwu   - machhwu.   */
5565
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5566
/* machhwuo  - machhwuo.  */
5567
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5568
/* maclhw    - maclhw.    */
5569
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5570
/* maclhwo   - maclhwo.   */
5571
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5572
/* maclhws   - maclhws.   */
5573
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5574
/* maclhwso  - maclhwso.  */
5575
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5576
/* maclhwu   - maclhwu.   */
5577
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5578
/* maclhwuo  - maclhwuo.  */
5579
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5580
/* maclhwsu  - maclhwsu.  */
5581
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5582
/* maclhwsuo - maclhwsuo. */
5583
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5584
/* nmacchw   - nmacchw.   */
5585
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5586
/* nmacchwo  - nmacchwo.  */
5587
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5588
/* nmacchws  - nmacchws.  */
5589
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5590
/* nmacchwso - nmacchwso. */
5591
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5592
/* nmachhw   - nmachhw.   */
5593
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5594
/* nmachhwo  - nmachhwo.  */
5595
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5596
/* nmachhws  - nmachhws.  */
5597
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5598
/* nmachhwso - nmachhwso. */
5599
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5600
/* nmaclhw   - nmaclhw.   */
5601
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5602
/* nmaclhwo  - nmaclhwo.  */
5603
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5604
/* nmaclhws  - nmaclhws.  */
5605
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5606
/* nmaclhwso - nmaclhwso. */
5607
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5608 5609

/* mulchw  - mulchw.  */
5610
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5611
/* mulchwu - mulchwu. */
5612
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5613
/* mulhhw  - mulhhw.  */
5614
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5615
/* mulhhwu - mulhhwu. */
5616
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5617
/* mullhw  - mullhw.  */
5618
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5619
/* mullhwu - mullhwu. */
5620
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5621 5622

/* mfdcr */
5623
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
5624 5625
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5626
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5627
#else
5628
    TCGv dcrn;
A
aurel32 已提交
5629
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5630
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5631 5632
        return;
    }
5633 5634 5635 5636 5637
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    dcrn = tcg_const_tl(SPR(ctx->opcode));
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
    tcg_temp_free(dcrn);
5638 5639 5640 5641
#endif
}

/* mtdcr */
5642
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
5643 5644
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5645
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5646
#else
5647
    TCGv dcrn;
A
aurel32 已提交
5648
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5649
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5650 5651
        return;
    }
5652 5653 5654 5655 5656
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    dcrn = tcg_const_tl(SPR(ctx->opcode));
    gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
    tcg_temp_free(dcrn);
5657 5658 5659 5660
#endif
}

/* mfdcrx */
5661
/* XXX: not implemented on 440 ? */
5662
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
5663 5664
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5665
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5666
#else
A
aurel32 已提交
5667
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5668
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5669 5670
        return;
    }
5671 5672 5673
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5674
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5675 5676 5677 5678
#endif
}

/* mtdcrx */
5679
/* XXX: not implemented on 440 ? */
5680
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
5681 5682
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5683
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5684
#else
A
aurel32 已提交
5685
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5686
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5687 5688
        return;
    }
5689 5690 5691
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5692
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5693 5694 5695
#endif
}

5696 5697 5698
/* mfdcrux (PPC 460) : user-mode access to DCR */
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
{
5699 5700 5701
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5702 5703 5704 5705 5706 5707
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

/* mtdcrux (PPC 460) : user-mode access to DCR */
GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
{
5708 5709 5710
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5711 5712 5713
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5714 5715 5716 5717
/* dccci */
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5718
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5719
#else
A
aurel32 已提交
5720
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5721
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5722 5723 5724 5725 5726 5727 5728 5729 5730 5731
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5732
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5733
#else
A
aurel32 已提交
5734
    TCGv EA, val;
A
aurel32 已提交
5735
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5736
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5737 5738
        return;
    }
A
aurel32 已提交
5739
    gen_set_access_type(ctx, ACCESS_CACHE);
P
pbrook 已提交
5740
    EA = tcg_temp_new();
A
aurel32 已提交
5741
    gen_addr_reg_index(ctx, EA);
P
pbrook 已提交
5742
    val = tcg_temp_new();
A
aurel32 已提交
5743
    gen_qemu_ld32u(ctx, val, EA);
A
aurel32 已提交
5744 5745 5746
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5747 5748 5749 5750
#endif
}

/* icbt */
5751
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
}

/* iccci */
GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5763
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5764
#else
A
aurel32 已提交
5765
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5766
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5767 5768 5769 5770 5771 5772 5773 5774 5775 5776
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5777
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5778
#else
A
aurel32 已提交
5779
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5780
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5781 5782 5783 5784 5785 5786
        return;
    }
    /* interpreted as no-op */
#endif
}

A
aurel32 已提交
5787
/* rfci (mem_idx only) */
5788
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
5789 5790
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5791
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5792
#else
A
aurel32 已提交
5793
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5794
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5795 5796 5797
        return;
    }
    /* Restore CPU state */
5798
    gen_helper_40x_rfci();
A
aurel32 已提交
5799
    gen_sync_exception(ctx);
5800 5801 5802 5803 5804 5805
#endif
}

GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5806
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5807
#else
A
aurel32 已提交
5808
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5809
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5810 5811 5812
        return;
    }
    /* Restore CPU state */
5813
    gen_helper_rfci();
A
aurel32 已提交
5814
    gen_sync_exception(ctx);
5815 5816 5817 5818
#endif
}

/* BookE specific */
5819
/* XXX: not implemented on 440 ? */
5820
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
5821 5822
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5823
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5824
#else
A
aurel32 已提交
5825
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5826
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5827 5828 5829
        return;
    }
    /* Restore CPU state */
5830
    gen_helper_rfdi();
A
aurel32 已提交
5831
    gen_sync_exception(ctx);
5832 5833 5834
#endif
}

5835
/* XXX: not implemented on 440 ? */
5836
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
5837 5838
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5839
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5840
#else
A
aurel32 已提交
5841
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5842
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5843 5844 5845
        return;
    }
    /* Restore CPU state */
5846
    gen_helper_rfmci();
A
aurel32 已提交
5847
    gen_sync_exception(ctx);
5848 5849
#endif
}
5850

5851
/* TLB management - PowerPC 405 implementation */
5852
/* tlbre */
5853
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
5854 5855
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5856
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5857
#else
A
aurel32 已提交
5858
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5859
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5860 5861 5862 5863
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5864
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5865 5866
        break;
    case 1:
5867
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5868 5869
        break;
    default:
A
aurel32 已提交
5870
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5871
        break;
5872
    }
5873 5874 5875
#endif
}

5876
/* tlbsx - tlbsx. */
5877
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5878 5879
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5880
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5881
#else
5882
    TCGv t0;
A
aurel32 已提交
5883
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5884
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5885 5886
        return;
    }
5887
    t0 = tcg_temp_new();
A
aurel32 已提交
5888
    gen_addr_reg_index(ctx, t0);
5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
        gen_set_label(l1);
    }
5900
#endif
B
bellard 已提交
5901 5902
}

5903
/* tlbwe */
5904
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
B
bellard 已提交
5905
{
5906
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5907
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5908
#else
A
aurel32 已提交
5909
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5910
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5911 5912 5913 5914
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5915
        gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5916 5917
        break;
    case 1:
5918
        gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5919 5920
        break;
    default:
A
aurel32 已提交
5921
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5922
        break;
5923
    }
5924 5925 5926
#endif
}

5927
/* TLB management - PowerPC 440 implementation */
5928
/* tlbre */
5929
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5930 5931
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5932
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5933
#else
A
aurel32 已提交
5934
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5935
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5936 5937 5938 5939 5940 5941
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5942 5943 5944 5945 5946
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
            gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
            tcg_temp_free_i32(t0);
        }
5947 5948
        break;
    default:
A
aurel32 已提交
5949
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5950 5951 5952 5953 5954 5955
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
5956
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5957 5958
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5959
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5960
#else
5961
    TCGv t0;
A
aurel32 已提交
5962
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5963
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5964 5965
        return;
    }
5966
    t0 = tcg_temp_new();
A
aurel32 已提交
5967
    gen_addr_reg_index(ctx, t0);
5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
    if (Rc(ctx->opcode)) {
        int l1 = gen_new_label();
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
        gen_set_label(l1);
    }
5979 5980 5981 5982
#endif
}

/* tlbwe */
5983
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5984 5985
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
5986
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5987
#else
A
aurel32 已提交
5988
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
5989
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5990 5991 5992 5993 5994 5995
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
5996 5997 5998 5999 6000
        {
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
            gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
            tcg_temp_free_i32(t0);
        }
6001 6002
        break;
    default:
A
aurel32 已提交
6003
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6004 6005 6006 6007 6008
        break;
    }
#endif
}

6009
/* wrtee */
6010
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
6011 6012
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6013
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6014
#else
6015
    TCGv t0;
A
aurel32 已提交
6016
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6017
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6018 6019
        return;
    }
6020 6021 6022 6023 6024
    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 已提交
6025 6026 6027
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
A
aurel32 已提交
6028
    gen_stop_exception(ctx);
6029 6030 6031 6032
#endif
}

/* wrteei */
6033
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
6034 6035
{
#if defined(CONFIG_USER_ONLY)
A
aurel32 已提交
6036
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6037
#else
A
aurel32 已提交
6038
    if (unlikely(!ctx->mem_idx)) {
A
aurel32 已提交
6039
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6040 6041
        return;
    }
6042 6043 6044
    if (ctx->opcode & 0x00010000) {
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
        /* Stop translation to have a chance to raise an exception */
A
aurel32 已提交
6045
        gen_stop_exception(ctx);
6046
    } else {
A
aurel32 已提交
6047
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6048
    }
6049 6050 6051
#endif
}

J
j_mayer 已提交
6052
/* PowerPC 440 specific instructions */
6053 6054 6055
/* dlmzb */
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
{
6056 6057 6058 6059
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
                     cpu_gpr[rB(ctx->opcode)], t0);
    tcg_temp_free_i32(t0);
6060 6061 6062
}

/* mbar replaces eieio on 440 */
A
aurel32 已提交
6063
GEN_HANDLER(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, PPC_BOOKE)
6064 6065 6066 6067 6068
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
6069
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
6070 6071 6072 6073 6074
{
    /* interpreted as no-op */
}

/* icbt */
6075
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
6076 6077 6078 6079 6080
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
6081 6082
}

6083 6084 6085
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

A
aurel32 已提交
6086 6087
static always_inline TCGv_ptr gen_avr_ptr(int reg)
{
A
aurel32 已提交
6088
    TCGv_ptr r = tcg_temp_new_ptr();
A
aurel32 已提交
6089 6090 6091 6092
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
    return r;
}

6093
#define GEN_VR_LDX(name, opc2, opc3)                                          \
6094
GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)                  \
6095
{                                                                             \
6096
    TCGv EA;                                                                  \
6097
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6098
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6099 6100
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6101
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6102
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6103
    gen_addr_reg_index(ctx, EA);                                              \
6104
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6105 6106
    if (ctx->le_mode) {                                                       \
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6107
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6108
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6109
    } else {                                                                  \
A
aurel32 已提交
6110
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6111
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6112
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6113 6114
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6115 6116 6117 6118 6119
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)              \
{                                                                             \
6120
    TCGv EA;                                                                  \
6121
    if (unlikely(!ctx->altivec_enabled)) {                                    \
A
aurel32 已提交
6122
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6123 6124
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6125
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6126
    EA = tcg_temp_new();                                                      \
A
aurel32 已提交
6127
    gen_addr_reg_index(ctx, EA);                                              \
6128
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
A
aurel32 已提交
6129 6130
    if (ctx->le_mode) {                                                       \
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6131
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6132
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6133
    } else {                                                                  \
A
aurel32 已提交
6134
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6135
        tcg_gen_addi_tl(EA, EA, 8);                                           \
A
aurel32 已提交
6136
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6137 6138
    }                                                                         \
    tcg_temp_free(EA);                                                        \
6139 6140
}

A
aurel32 已提交
6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176
#define GEN_VR_LVE(name, opc2, opc3)                                    \
    GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)   \
    {                                                                   \
        TCGv EA;                                                        \
        TCGv_ptr rs;                                                    \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        gen_set_access_type(ctx, ACCESS_INT);                           \
        EA = tcg_temp_new();                                            \
        gen_addr_reg_index(ctx, EA);                                    \
        rs = gen_avr_ptr(rS(ctx->opcode));                              \
        gen_helper_lve##name (rs, EA);                                  \
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

#define GEN_VR_STVE(name, opc2, opc3)                                   \
    GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)  \
    {                                                                   \
        TCGv EA;                                                        \
        TCGv_ptr rs;                                                    \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        gen_set_access_type(ctx, ACCESS_INT);                           \
        EA = tcg_temp_new();                                            \
        gen_addr_reg_index(ctx, EA);                                    \
        rs = gen_avr_ptr(rS(ctx->opcode));                              \
        gen_helper_stve##name (rs, EA);                                 \
        tcg_temp_free(EA);                                              \
        tcg_temp_free_ptr(rs);                                          \
    }

6177
GEN_VR_LDX(lvx, 0x07, 0x03);
6178
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6179
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6180

A
aurel32 已提交
6181 6182 6183 6184
GEN_VR_LVE(bx, 0x07, 0x00);
GEN_VR_LVE(hx, 0x07, 0x01);
GEN_VR_LVE(wx, 0x07, 0x02);

6185
GEN_VR_STX(svx, 0x07, 0x07);
6186
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6187
GEN_VR_STX(svxl, 0x07, 0x0F);
6188

A
aurel32 已提交
6189 6190 6191 6192
GEN_VR_STVE(bx, 0x07, 0x04);
GEN_VR_STVE(hx, 0x07, 0x05);
GEN_VR_STVE(wx, 0x07, 0x06);

A
aurel32 已提交
6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC)
{
    TCGv_ptr rd;
    TCGv EA;
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    EA = tcg_temp_new();
    gen_addr_reg_index(ctx, EA);
    rd = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_lvsl(rd, EA);
    tcg_temp_free(EA);
    tcg_temp_free_ptr(rd);
}

GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC)
{
    TCGv_ptr rd;
    TCGv EA;
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    EA = tcg_temp_new();
    gen_addr_reg_index(ctx, EA);
    rd = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_lvsr(rd, EA);
    tcg_temp_free(EA);
    tcg_temp_free_ptr(rd);
}

6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235
GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC)
{
    TCGv_i32 t;
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
    t = tcg_temp_new_i32();
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, vscr));
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6236
    tcg_temp_free_i32(t);
6237 6238 6239 6240
}

GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC)
{
A
aurel32 已提交
6241
    TCGv_ptr p;
6242 6243 6244 6245
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
A
aurel32 已提交
6246 6247 6248
    p = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_mtvscr(p);
    tcg_temp_free_ptr(p);
6249 6250
}

6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)            \
{                                                                       \
    if (unlikely(!ctx->altivec_enabled)) {                              \
        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
        return;                                                         \
    }                                                                   \
    tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
    tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
}

GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);

6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285
#define GEN_VXFORM(name, opc2, opc3)                                    \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)            \
{                                                                       \
    TCGv_ptr ra, rb, rd;                                                \
    if (unlikely(!ctx->altivec_enabled)) {                              \
        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
        return;                                                         \
    }                                                                   \
    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
    gen_helper_##name (rd, ra, rb);                                     \
    tcg_temp_free_ptr(ra);                                              \
    tcg_temp_free_ptr(rb);                                              \
    tcg_temp_free_ptr(rd);                                              \
}

A
aurel32 已提交
6286 6287 6288 6289 6290 6291
GEN_VXFORM(vaddubm, 0, 0);
GEN_VXFORM(vadduhm, 0, 1);
GEN_VXFORM(vadduwm, 0, 2);
GEN_VXFORM(vsububm, 0, 16);
GEN_VXFORM(vsubuhm, 0, 17);
GEN_VXFORM(vsubuwm, 0, 18);
6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303
GEN_VXFORM(vmaxub, 1, 0);
GEN_VXFORM(vmaxuh, 1, 1);
GEN_VXFORM(vmaxuw, 1, 2);
GEN_VXFORM(vmaxsb, 1, 4);
GEN_VXFORM(vmaxsh, 1, 5);
GEN_VXFORM(vmaxsw, 1, 6);
GEN_VXFORM(vminub, 1, 8);
GEN_VXFORM(vminuh, 1, 9);
GEN_VXFORM(vminuw, 1, 10);
GEN_VXFORM(vminsb, 1, 12);
GEN_VXFORM(vminsh, 1, 13);
GEN_VXFORM(vminsw, 1, 14);
A
aurel32 已提交
6304 6305 6306 6307 6308 6309
GEN_VXFORM(vavgub, 1, 16);
GEN_VXFORM(vavguh, 1, 17);
GEN_VXFORM(vavguw, 1, 18);
GEN_VXFORM(vavgsb, 1, 20);
GEN_VXFORM(vavgsh, 1, 21);
GEN_VXFORM(vavgsw, 1, 22);
A
aurel32 已提交
6310 6311 6312 6313 6314 6315
GEN_VXFORM(vmrghb, 6, 0);
GEN_VXFORM(vmrghh, 6, 1);
GEN_VXFORM(vmrghw, 6, 2);
GEN_VXFORM(vmrglb, 6, 4);
GEN_VXFORM(vmrglh, 6, 5);
GEN_VXFORM(vmrglw, 6, 6);
A
aurel32 已提交
6316 6317 6318 6319 6320 6321 6322 6323
GEN_VXFORM(vmuloub, 4, 0);
GEN_VXFORM(vmulouh, 4, 1);
GEN_VXFORM(vmulosb, 4, 4);
GEN_VXFORM(vmulosh, 4, 5);
GEN_VXFORM(vmuleub, 4, 8);
GEN_VXFORM(vmuleuh, 4, 9);
GEN_VXFORM(vmulesb, 4, 12);
GEN_VXFORM(vmulesh, 4, 13);
A
aurel32 已提交
6324 6325 6326
GEN_VXFORM(vslb, 2, 4);
GEN_VXFORM(vslh, 2, 5);
GEN_VXFORM(vslw, 2, 6);
A
aurel32 已提交
6327 6328 6329 6330 6331 6332
GEN_VXFORM(vsrb, 2, 8);
GEN_VXFORM(vsrh, 2, 9);
GEN_VXFORM(vsrw, 2, 10);
GEN_VXFORM(vsrab, 2, 12);
GEN_VXFORM(vsrah, 2, 13);
GEN_VXFORM(vsraw, 2, 14);
A
aurel32 已提交
6333 6334
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
A
aurel32 已提交
6335 6336
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348
GEN_VXFORM(vaddubs, 0, 8);
GEN_VXFORM(vadduhs, 0, 9);
GEN_VXFORM(vadduws, 0, 10);
GEN_VXFORM(vaddsbs, 0, 12);
GEN_VXFORM(vaddshs, 0, 13);
GEN_VXFORM(vaddsws, 0, 14);
GEN_VXFORM(vsububs, 0, 24);
GEN_VXFORM(vsubuhs, 0, 25);
GEN_VXFORM(vsubuws, 0, 26);
GEN_VXFORM(vsubsbs, 0, 28);
GEN_VXFORM(vsubshs, 0, 29);
GEN_VXFORM(vsubsws, 0, 30);
A
aurel32 已提交
6349 6350 6351
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
A
aurel32 已提交
6352 6353
GEN_VXFORM(vsl, 2, 7);
GEN_VXFORM(vsr, 2, 11);
6354 6355 6356 6357 6358 6359 6360 6361
GEN_VXFORM(vpkuhum, 7, 0);
GEN_VXFORM(vpkuwum, 7, 1);
GEN_VXFORM(vpkuhus, 7, 2);
GEN_VXFORM(vpkuwus, 7, 3);
GEN_VXFORM(vpkshus, 7, 4);
GEN_VXFORM(vpkswus, 7, 5);
GEN_VXFORM(vpkshss, 7, 6);
GEN_VXFORM(vpkswss, 7, 7);
A
aurel32 已提交
6362
GEN_VXFORM(vpkpx, 7, 12);
6363 6364 6365 6366 6367
GEN_VXFORM(vsum4ubs, 4, 24);
GEN_VXFORM(vsum4sbs, 4, 28);
GEN_VXFORM(vsum4shs, 4, 25);
GEN_VXFORM(vsum2sws, 4, 26);
GEN_VXFORM(vsumsws, 4, 30);
6368 6369
GEN_VXFORM(vaddfp, 5, 0);
GEN_VXFORM(vsubfp, 5, 1);
6370 6371
GEN_VXFORM(vmaxfp, 5, 16);
GEN_VXFORM(vminfp, 5, 17);
A
aurel32 已提交
6372

6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
    GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC)   \
    {                                                                   \
        TCGv_ptr ra, rb, rd;                                            \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        ra = gen_avr_ptr(rA(ctx->opcode));                              \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##opname (rd, ra, rb);                               \
        tcg_temp_free_ptr(ra);                                          \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

#define GEN_VXRFORM(name, opc2, opc3)                                \
    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))

6394 6395 6396 6397 6398 6399 6400 6401 6402
GEN_VXRFORM(vcmpequb, 3, 0)
GEN_VXRFORM(vcmpequh, 3, 1)
GEN_VXRFORM(vcmpequw, 3, 2)
GEN_VXRFORM(vcmpgtsb, 3, 12)
GEN_VXRFORM(vcmpgtsh, 3, 13)
GEN_VXRFORM(vcmpgtsw, 3, 14)
GEN_VXRFORM(vcmpgtub, 3, 8)
GEN_VXRFORM(vcmpgtuh, 3, 9)
GEN_VXRFORM(vcmpgtuw, 3, 10)
6403 6404 6405 6406
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
6407

A
aurel32 已提交
6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)        \
    {                                                                   \
        TCGv_ptr rd;                                                    \
        TCGv_i32 simm;                                                  \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name (rd, simm);                                   \
        tcg_temp_free_i32(simm);                                        \
        tcg_temp_free_ptr(rd);                                          \
    }

GEN_VXFORM_SIMM(vspltisb, 6, 12);
GEN_VXFORM_SIMM(vspltish, 6, 13);
GEN_VXFORM_SIMM(vspltisw, 6, 14);

6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)        \
    {                                                                   \
        TCGv_ptr rb, rd;                                                \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name (rd, rb);                                     \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                         \
    }

A
aurel32 已提交
6443 6444 6445 6446
GEN_VXFORM_NOA(vupkhsb, 7, 8);
GEN_VXFORM_NOA(vupkhsh, 7, 9);
GEN_VXFORM_NOA(vupklsb, 7, 10);
GEN_VXFORM_NOA(vupklsh, 7, 11);
A
aurel32 已提交
6447 6448
GEN_VXFORM_NOA(vupkhpx, 7, 13);
GEN_VXFORM_NOA(vupklpx, 7, 15);
A
aurel32 已提交
6449
GEN_VXFORM_NOA(vrefp, 5, 4);
A
aurel32 已提交
6450
GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
6451
GEN_VXFORM_NOA(vlogefp, 5, 7);
A
aurel32 已提交
6452 6453 6454 6455
GEN_VXFORM_NOA(vrfim, 5, 8);
GEN_VXFORM_NOA(vrfin, 5, 9);
GEN_VXFORM_NOA(vrfip, 5, 10);
GEN_VXFORM_NOA(vrfiz, 5, 11);
A
aurel32 已提交
6456

6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)        \
    {                                                                   \
        TCGv_ptr rd;                                                    \
        TCGv_i32 simm;                                                  \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name (rd, simm);                                   \
        tcg_temp_free_i32(simm);                                        \
        tcg_temp_free_ptr(rd);                                          \
    }

6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)        \
    {                                                                   \
        TCGv_ptr rb, rd;                                                \
        TCGv_i32 uimm;                                                  \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        gen_helper_##name (rd, rb, uimm);                               \
        tcg_temp_free_i32(uimm);                                        \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6491 6492 6493
GEN_VXFORM_UIMM(vspltb, 6, 8);
GEN_VXFORM_UIMM(vsplth, 6, 9);
GEN_VXFORM_UIMM(vspltw, 6, 10);
A
aurel32 已提交
6494 6495
GEN_VXFORM_UIMM(vcfux, 5, 12);
GEN_VXFORM_UIMM(vcfsx, 5, 13);
6496 6497
GEN_VXFORM_UIMM(vctuxs, 5, 14);
GEN_VXFORM_UIMM(vctsxs, 5, 15);
A
aurel32 已提交
6498

A
aurel32 已提交
6499 6500 6501
GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC)
{
    TCGv_ptr ra, rb, rd;
6502
    TCGv_i32 sh;
A
aurel32 已提交
6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    ra = gen_avr_ptr(rA(ctx->opcode));
    rb = gen_avr_ptr(rB(ctx->opcode));
    rd = gen_avr_ptr(rD(ctx->opcode));
    sh = tcg_const_i32(VSH(ctx->opcode));
    gen_helper_vsldoi (rd, ra, rb, sh);
    tcg_temp_free_ptr(ra);
    tcg_temp_free_ptr(rb);
    tcg_temp_free_ptr(rd);
6515
    tcg_temp_free_i32(sh);
A
aurel32 已提交
6516 6517
}

6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
    GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC) \
    {                                                                   \
        TCGv_ptr ra, rb, rc, rd;                                        \
        if (unlikely(!ctx->altivec_enabled)) {                          \
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
            return;                                                     \
        }                                                               \
        ra = gen_avr_ptr(rA(ctx->opcode));                              \
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
        rc = gen_avr_ptr(rC(ctx->opcode));                              \
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
        if (Rc(ctx->opcode)) {                                          \
            gen_helper_##name1 (rd, ra, rb, rc);                        \
        } else {                                                        \
            gen_helper_##name0 (rd, ra, rb, rc);                        \
        }                                                               \
        tcg_temp_free_ptr(ra);                                          \
        tcg_temp_free_ptr(rb);                                          \
        tcg_temp_free_ptr(rc);                                          \
        tcg_temp_free_ptr(rd);                                          \
    }

A
aurel32 已提交
6541 6542
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)

A
aurel32 已提交
6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560
GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC)
{
    TCGv_ptr ra, rb, rc, rd;
    if (unlikely(!ctx->altivec_enabled)) {
        gen_exception(ctx, POWERPC_EXCP_VPU);
        return;
    }
    ra = gen_avr_ptr(rA(ctx->opcode));
    rb = gen_avr_ptr(rB(ctx->opcode));
    rc = gen_avr_ptr(rC(ctx->opcode));
    rd = gen_avr_ptr(rD(ctx->opcode));
    gen_helper_vmladduhm(rd, ra, rb, rc);
    tcg_temp_free_ptr(ra);
    tcg_temp_free_ptr(rb);
    tcg_temp_free_ptr(rc);
    tcg_temp_free_ptr(rd);
}

A
aurel32 已提交
6561
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
A
aurel32 已提交
6562
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
A
aurel32 已提交
6563
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
A
aurel32 已提交
6564
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6565
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
A
aurel32 已提交
6566

6567 6568
/***                           SPE extension                               ***/
/* Register moves */
6569

P
pbrook 已提交
6570
static always_inline void gen_load_gpr64(TCGv_i64 t, int reg) {
A
aurel32 已提交
6571 6572 6573
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
6574
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6575
#endif
A
aurel32 已提交
6576
}
6577

P
pbrook 已提交
6578
static always_inline void gen_store_gpr64(int reg, TCGv_i64 t) {
A
aurel32 已提交
6579 6580 6581
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
6582
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
6583 6584 6585
    tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
    tcg_gen_shri_i64(tmp, t, 32);
    tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
P
pbrook 已提交
6586
    tcg_temp_free_i64(tmp);
6587
#endif
A
aurel32 已提交
6588
}
6589

6590 6591 6592 6593 6594 6595 6596 6597 6598 6599
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)                   \
{                                                                             \
    if (Rc(ctx->opcode))                                                      \
        gen_##name1(ctx);                                                     \
    else                                                                      \
        gen_##name0(ctx);                                                     \
}

/* Handler for undefined SPE opcodes */
6600
static always_inline void gen_speundef (DisasContext *ctx)
6601
{
A
aurel32 已提交
6602
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6603 6604
}

6605 6606 6607
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
6608
static always_inline void gen_##name (DisasContext *ctx)                      \
6609 6610
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6611
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6612 6613
        return;                                                               \
    }                                                                         \
6614 6615 6616 6617 6618 6619 6620 6621
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
           cpu_gpr[rB(ctx->opcode)]);                                         \
}
#else
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6622
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6623 6624 6625 6626 6627 6628
        return;                                                               \
    }                                                                         \
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
           cpu_gpr[rB(ctx->opcode)]);                                         \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
           cpu_gprh[rB(ctx->opcode)]);                                        \
6629
}
6630 6631 6632 6633 6634 6635 6636 6637 6638 6639
#endif

GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
6640

6641 6642 6643
/* SPE logic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
6644 6645 6646
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6647
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6648 6649
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6650 6651 6652
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6653 6654 6655 6656
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_opi(t0, t0, rB(ctx->opcode));                                         \
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
6657
    tcg_temp_free_i64(t2);                                                    \
6658 6659
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6660 6661
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6662
}
6663 6664
#else
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
6665
static always_inline void gen_##name (DisasContext *ctx)                      \
6666 6667
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6668
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6669 6670
        return;                                                               \
    }                                                                         \
6671 6672 6673 6674
    tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],               \
            rB(ctx->opcode));                                                 \
    tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],             \
            rB(ctx->opcode));                                                 \
6675
}
6676 6677 6678 6679 6680
#endif
GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
6681

6682 6683 6684
/* SPE arithmetic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6685
static always_inline void gen_##name (DisasContext *ctx)                      \
6686 6687
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6688
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6689 6690
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6691 6692 6693
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6694 6695 6696 6697
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_op(t0, t0);                                                           \
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
6698
    tcg_temp_free_i64(t2);                                                    \
6699 6700
    tcg_op(t1, t1);                                                           \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6701 6702
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6703
}
6704
#else
P
pbrook 已提交
6705
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6706 6707 6708
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6709
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6710 6711 6712 6713 6714 6715
        return;                                                               \
    }                                                                         \
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);               \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);             \
}
#endif
6716

P
pbrook 已提交
6717
static always_inline void gen_op_evabs (TCGv_i32 ret, TCGv_i32 arg1)
6718 6719 6720
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
6721

6722 6723 6724 6725
    tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
    tcg_gen_neg_i32(ret, arg1);
    tcg_gen_br(l2);
    gen_set_label(l1);
P
pbrook 已提交
6726
    tcg_gen_mov_i32(ret, arg1);
6727 6728 6729 6730 6731 6732
    gen_set_label(l2);
}
GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
P
pbrook 已提交
6733
static always_inline void gen_op_evrndw (TCGv_i32 ret, TCGv_i32 arg1)
6734
{
6735 6736 6737 6738
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
6739 6740
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6741

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

P
pbrook 已提交
6783
static always_inline void gen_op_evsrwu (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6784
{
P
pbrook 已提交
6785
    TCGv_i32 t0;
6786
    int l1, l2;
6787

6788 6789
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6790
    t0 = tcg_temp_local_new_i32();
6791 6792 6793 6794 6795 6796 6797 6798
    /* No error here: 6 bits are used */
    tcg_gen_andi_i32(t0, arg2, 0x3F);
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
    tcg_gen_shr_i32(ret, arg1, t0);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_i32(ret, 0);
    tcg_gen_br(l2);
P
pbrook 已提交
6799
    tcg_temp_free_i32(t0);
6800 6801
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
P
pbrook 已提交
6802
static always_inline void gen_op_evsrws (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6803
{
P
pbrook 已提交
6804
    TCGv_i32 t0;
6805 6806 6807 6808
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6809
    t0 = tcg_temp_local_new_i32();
6810 6811 6812 6813 6814 6815 6816 6817
    /* No error here: 6 bits are used */
    tcg_gen_andi_i32(t0, arg2, 0x3F);
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
    tcg_gen_sar_i32(ret, arg1, t0);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_i32(ret, 0);
    tcg_gen_br(l2);
P
pbrook 已提交
6818
    tcg_temp_free_i32(t0);
6819 6820
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
P
pbrook 已提交
6821
static always_inline void gen_op_evslw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6822
{
P
pbrook 已提交
6823
    TCGv_i32 t0;
6824 6825 6826 6827
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6828
    t0 = tcg_temp_local_new_i32();
6829 6830 6831 6832 6833 6834 6835 6836
    /* No error here: 6 bits are used */
    tcg_gen_andi_i32(t0, arg2, 0x3F);
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
    tcg_gen_shl_i32(ret, arg1, t0);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_i32(ret, 0);
    tcg_gen_br(l2);
P
pbrook 已提交
6837
    tcg_temp_free_i32(t0);
6838 6839
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
P
pbrook 已提交
6840
static always_inline void gen_op_evrlw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6841
{
P
pbrook 已提交
6842
    TCGv_i32 t0 = tcg_temp_new_i32();
6843 6844
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
6845
    tcg_temp_free_i32(t0);
6846 6847 6848 6849 6850
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
static always_inline void gen_evmergehi (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
6851
        gen_exception(ctx, POWERPC_EXCP_APU);
6852 6853 6854
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6855 6856
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
}
GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
P
pbrook 已提交
6868
static always_inline void gen_op_evsubf (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6869
{
6870 6871 6872
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
6873

6874 6875 6876 6877 6878 6879
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6880
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6881 6882
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6883 6884 6885
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6886 6887 6888 6889
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]);                      \
    tcg_op(t0, t0, rA(ctx->opcode));                                          \
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
A
aurel32 已提交
6890
    tcg_temp_free_i64(t2);                                                    \
6891 6892
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6893 6894
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6895 6896 6897 6898 6899 6900
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6901
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918
        return;                                                               \
    }                                                                         \
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],                \
           rA(ctx->opcode));                                                  \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)],              \
           rA(ctx->opcode));                                                  \
}
#endif
GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);

/* SPE comparison */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6919
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6920 6921 6922 6923 6924 6925
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
6926 6927 6928
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6929 6930 6931
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]);                      \
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l1);                                 \
P
pbrook 已提交
6932
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
6933 6934 6935 6936 6937 6938 6939 6940 6941
    tcg_gen_br(l2);                                                           \
    gen_set_label(l1);                                                        \
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
    gen_set_label(l2);                                                        \
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t0, t2);                                            \
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
6942
    tcg_temp_free_i64(t2);                                                    \
6943 6944 6945 6946 6947 6948 6949 6950
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l3);                                 \
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
    tcg_gen_br(l4);                                                           \
    gen_set_label(l3);                                                        \
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
                    CRF_CH | CRF_CH_OR_CL);                                   \
    gen_set_label(l4);                                                        \
P
pbrook 已提交
6951 6952
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6953 6954 6955 6956 6957 6958
}
#else
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
6959
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
                                                                              \
    tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)],                    \
                       cpu_gpr[rB(ctx->opcode)], l1);                         \
    tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0);                           \
    tcg_gen_br(l2);                                                           \
    gen_set_label(l1);                                                        \
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
    gen_set_label(l2);                                                        \
    tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)],                   \
                       cpu_gprh[rB(ctx->opcode)], l3);                        \
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
    tcg_gen_br(l4);                                                           \
    gen_set_label(l3);                                                        \
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
                    CRF_CH | CRF_CH_OR_CL);                                   \
    gen_set_label(l4);                                                        \
}
#endif
GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);

/* SPE misc */
static always_inline void gen_brinc (DisasContext *ctx)
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
6996 6997
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6998
}
6999 7000 7001
static always_inline void gen_evmergelo (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7002
        gen_exception(ctx, POWERPC_EXCP_APU);
7003 7004 7005
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7006 7007
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
#endif
}
static always_inline void gen_evmergehilo (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7021
        gen_exception(ctx, POWERPC_EXCP_APU);
7022 7023 7024
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7025 7026
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
}
static always_inline void gen_evmergelohi (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7040
        gen_exception(ctx, POWERPC_EXCP_APU);
7041 7042 7043
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
7044 7045
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
#endif
}
static always_inline void gen_evsplati (DisasContext *ctx)
{
7058
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 11)) >> 27;
7059

7060
#if defined(TARGET_PPC64)
7061
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7062 7063 7064 7065 7066
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
}
7067
static always_inline void gen_evsplatfi (DisasContext *ctx)
7068
{
7069
    uint64_t imm = rA(ctx->opcode) << 11;
7070

7071
#if defined(TARGET_PPC64)
7072
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7073 7074 7075 7076
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
7077 7078
}

7079 7080 7081 7082 7083 7084
static always_inline void gen_evsel (DisasContext *ctx)
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
7085
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7086
#if defined(TARGET_PPC64)
P
pbrook 已提交
7087 7088
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119
#endif
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
    tcg_gen_br(l2);
    gen_set_label(l1);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
#endif
    gen_set_label(l2);
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
#endif
    tcg_gen_br(l4);
    gen_set_label(l3);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
7120
    tcg_temp_free_i32(t0);
7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142
#if defined(TARGET_PPC64)
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
#endif
}
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
{
    gen_evsel(ctx);
}
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
{
    gen_evsel(ctx);
}
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
{
    gen_evsel(ctx);
}
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
{
    gen_evsel(ctx);
}
7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169

GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE); ////
GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE); ////
GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE); ////
GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE); //
GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE); //
GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE);
GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE); ////
GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE); ////
GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE); ////

7170
/* SPE load and stores */
A
aurel32 已提交
7171
static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, TCGv EA, int sh)
7172 7173 7174
{
    target_ulong uimm = rB(ctx->opcode);

A
aurel32 已提交
7175
    if (rA(ctx->opcode) == 0) {
7176
        tcg_gen_movi_tl(EA, uimm << sh);
A
aurel32 已提交
7177
    } else {
7178
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
A
aurel32 已提交
7179 7180 7181 7182 7183 7184
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode) {
            tcg_gen_ext32u_tl(EA, EA);
        }
#endif
    }
7185
}
7186 7187 7188 7189

static always_inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7190
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7191 7192
#else
    TCGv_i64 t0 = tcg_temp_new_i64();
A
aurel32 已提交
7193
    gen_qemu_ld64(ctx, t0, addr);
7194 7195 7196 7197 7198
    tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_temp_free_i64(t0);
#endif
7199
}
7200 7201 7202

static always_inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
{
7203
#if defined(TARGET_PPC64)
7204
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7205
    gen_qemu_ld32u(ctx, t0, addr);
7206
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
A
aurel32 已提交
7207 7208
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, t0, addr);
7209 7210 7211
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7212 7213 7214
    gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7215
#endif
7216
}
7217 7218 7219 7220 7221

static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7222
    gen_qemu_ld16u(ctx, t0, addr);
7223
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7224 7225
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7226 7227
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7228 7229
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7230 7231
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7232 7233
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7234
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7235
#else
A
aurel32 已提交
7236
    gen_qemu_ld16u(ctx, t0, addr);
7237
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7238 7239
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7240
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
A
aurel32 已提交
7241 7242
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7243
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7244 7245
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7246
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7247
#endif
7248
    tcg_temp_free(t0);
7249 7250
}

7251 7252 7253
static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7254
    gen_qemu_ld16u(ctx, t0, addr);
7255 7256 7257 7258 7259 7260 7261 7262 7263 7264
#if defined(TARGET_PPC64)
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
7265 7266
}

7267 7268 7269
static always_inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7270
    gen_qemu_ld16u(ctx, t0, addr);
7271 7272 7273 7274 7275 7276 7277 7278
#if defined(TARGET_PPC64)
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
7279 7280
}

7281 7282 7283
static always_inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7284
    gen_qemu_ld16s(ctx, t0, addr);
7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299
#if defined(TARGET_PPC64)
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
    tcg_gen_ext32u_tl(t0, t0);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
}

static always_inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
A
aurel32 已提交
7300
    gen_qemu_ld16u(ctx, t0, addr);
7301
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
A
aurel32 已提交
7302 7303
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7304 7305 7306
    tcg_gen_shli_tl(t0, t0, 16);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
A
aurel32 已提交
7307
    gen_qemu_ld16u(ctx, t0, addr);
7308
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
A
aurel32 已提交
7309 7310
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7311 7312 7313 7314 7315 7316 7317 7318 7319
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
#endif
    tcg_temp_free(t0);
}

static always_inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7320 7321 7322
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, t0, addr);
7323 7324 7325 7326
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7327 7328 7329
    gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7330 7331 7332 7333 7334 7335 7336
#endif
}

static always_inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7337
    gen_qemu_ld16s(ctx, t0, addr);
7338
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
A
aurel32 已提交
7339 7340
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, t0, addr);
7341 7342 7343 7344
    tcg_gen_shli_tl(t0, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7345 7346 7347
    gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7348 7349 7350 7351 7352 7353
#endif
}

static always_inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
{
    TCGv t0 = tcg_temp_new();
A
aurel32 已提交
7354
    gen_qemu_ld32u(ctx, t0, addr);
7355
#if defined(TARGET_PPC64)
7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
}

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

static always_inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
{
#if defined(TARGET_PPC64)
A
aurel32 已提交
7393
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7394
#else
7395 7396
    TCGv_i64 t0 = tcg_temp_new_i64();
    tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
A
aurel32 已提交
7397
    gen_qemu_st64(ctx, t0, addr);
7398 7399 7400 7401 7402 7403
    tcg_temp_free_i64(t0);
#endif
}

static always_inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
{
7404
#if defined(TARGET_PPC64)
7405 7406
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7407
    gen_qemu_st32(ctx, t0, addr);
7408 7409
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7410
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7411
#endif
A
aurel32 已提交
7412 7413
    gen_addr_add(ctx, addr, addr, 4);
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7414 7415 7416 7417 7418 7419 7420 7421 7422 7423
}

static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
#else
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
#endif
A
aurel32 已提交
7424 7425
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7426 7427
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7428
    gen_qemu_st16(ctx, t0, addr);
7429
#else
A
aurel32 已提交
7430
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7431
#endif
A
aurel32 已提交
7432
    gen_addr_add(ctx, addr, addr, 2);
7433
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7434
    gen_qemu_st16(ctx, t0, addr);
7435
    tcg_temp_free(t0);
A
aurel32 已提交
7436 7437
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7438 7439 7440 7441 7442 7443 7444 7445 7446 7447
}

static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
{
    TCGv t0 = tcg_temp_new();
#if defined(TARGET_PPC64)
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
#else
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
#endif
A
aurel32 已提交
7448 7449
    gen_qemu_st16(ctx, t0, addr);
    gen_addr_add(ctx, addr, addr, 2);
7450
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
A
aurel32 已提交
7451
    gen_qemu_st16(ctx, t0, addr);
7452 7453 7454 7455 7456 7457 7458 7459
    tcg_temp_free(t0);
}

static always_inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7460
    gen_qemu_st16(ctx, t0, addr);
7461 7462
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7463
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7464
#endif
A
aurel32 已提交
7465 7466
    gen_addr_add(ctx, addr, addr, 2);
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7467 7468 7469 7470 7471 7472 7473
}

static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
{
#if defined(TARGET_PPC64)
    TCGv t0 = tcg_temp_new();
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
A
aurel32 已提交
7474
    gen_qemu_st32(ctx, t0, addr);
7475 7476
    tcg_temp_free(t0);
#else
A
aurel32 已提交
7477
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7478 7479 7480 7481 7482
#endif
}

static always_inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
{
A
aurel32 已提交
7483
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7484 7485 7486
}

#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
A
aurel32 已提交
7487
GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)                      \
7488 7489 7490
{                                                                             \
    TCGv t0;                                                                  \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7491
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7492 7493
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7494
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7495 7496
    t0 = tcg_temp_new();                                                      \
    if (Rc(ctx->opcode)) {                                                    \
A
aurel32 已提交
7497
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7498
    } else {                                                                  \
A
aurel32 已提交
7499
        gen_addr_reg_index(ctx, t0);                                          \
7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523
    }                                                                         \
    gen_op_##name(ctx, t0);                                                   \
    tcg_temp_free(t0);                                                        \
}

GEN_SPEOP_LDST(evldd, 0x00, 3);
GEN_SPEOP_LDST(evldw, 0x01, 3);
GEN_SPEOP_LDST(evldh, 0x02, 3);
GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
GEN_SPEOP_LDST(evlwhe, 0x08, 2);
GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);

GEN_SPEOP_LDST(evstdd, 0x10, 3);
GEN_SPEOP_LDST(evstdw, 0x11, 3);
GEN_SPEOP_LDST(evstdh, 0x12, 3);
GEN_SPEOP_LDST(evstwhe, 0x18, 2);
GEN_SPEOP_LDST(evstwho, 0x1A, 2);
GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601

/* Multiply and add - TODO */
#if 0
GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, PPC_SPE);
GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0x00000000, PPC_SPE);

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

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

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

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

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

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

/***                      SPE floating-point extension                     ***/
A
aurel32 已提交
7602 7603
#if defined(TARGET_PPC64)
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
7604
static always_inline void gen_##name (DisasContext *ctx)                      \
7605
{                                                                             \
A
aurel32 已提交
7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
    gen_helper_##name(t0, t0);                                                \
    t1 = tcg_temp_new();                                                      \
    tcg_gen_extu_i32_tl(t1, t0);                                              \
    tcg_temp_free_i32(t0);                                                    \
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
                    0xFFFFFFFF00000000ULL);                                   \
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
    tcg_temp_free(t1);                                                        \
7618
}
A
aurel32 已提交
7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    TCGv_i32 t0;                                                              \
    TCGv t1;                                                                  \
    t0 = tcg_temp_new_i32();                                                  \
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
    t1 = tcg_temp_new();                                                      \
    tcg_gen_extu_i32_tl(t1, t0);                                              \
    tcg_temp_free_i32(t0);                                                    \
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
                    0xFFFFFFFF00000000ULL);                                   \
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
    tcg_temp_free(t1);                                                        \
}
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
    tcg_temp_free_i32(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
7648 7649
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
A
aurel32 已提交
7650 7651
    TCGv_i32 t0, t1;                                                          \
    TCGv_i64 t2;                                                              \
7652
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7653
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7654 7655
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668
    t0 = tcg_temp_new_i32();                                                  \
    t1 = tcg_temp_new_i32();                                                  \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
    gen_helper_##name(t0, t0, t1);                                            \
    tcg_temp_free_i32(t1);                                                    \
    t2 = tcg_temp_new();                                                      \
    tcg_gen_extu_i32_tl(t2, t0);                                              \
    tcg_temp_free_i32(t0);                                                    \
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
                    0xFFFFFFFF00000000ULL);                                   \
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2);    \
    tcg_temp_free(t2);                                                        \
7669
}
A
aurel32 已提交
7670
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
7671 7672 7673
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7674
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7675 7676
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7677 7678
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],     \
                      cpu_gpr[rB(ctx->opcode)]);                              \
7679
}
A
aurel32 已提交
7680
#define GEN_SPEFPUOP_COMP_32(name)                                            \
7681 7682
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
A
aurel32 已提交
7683
    TCGv_i32 t0, t1;                                                          \
7684
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7685
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7686 7687
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699
    t0 = tcg_temp_new_i32();                                                  \
    t1 = tcg_temp_new_i32();                                                  \
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7700
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7701 7702 7703 7704 7705 7706 7707 7708 7709 7710
        return;                                                               \
    }                                                                         \
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#else
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7711
}
A
aurel32 已提交
7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
    gen_helper_##name(t0, t0);                                                \
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7741
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7742 7743 7744 7745 7746 7747 7748 7749 7750 7751
        return;                                                               \
    }                                                                         \
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)],                               \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7752
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767
        return;                                                               \
    }                                                                         \
    t0 = tcg_temp_new_i64();                                                  \
    t1 = tcg_temp_new_i64();                                                  \
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
    gen_helper_##name(t0, t0, t1);                                            \
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free_i64(t0);                                                    \
    tcg_temp_free_i64(t1);                                                    \
}
#define GEN_SPEFPUOP_COMP_32(name)                                            \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7768
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7769 7770 7771 7772 7773 7774 7775 7776 7777 7778
        return;                                                               \
    }                                                                         \
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
}
#define GEN_SPEFPUOP_COMP_64(name)                                            \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    TCGv_i64 t0, t1;                                                          \
    if (unlikely(!ctx->spe_enabled)) {                                        \
A
aurel32 已提交
7779
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
A
aurel32 已提交
7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790
        return;                                                               \
    }                                                                         \
    t0 = tcg_temp_new_i64();                                                  \
    t1 = tcg_temp_new_i64();                                                  \
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
    tcg_temp_free_i64(t0);                                                    \
    tcg_temp_free_i64(t1);                                                    \
}
#endif
7791

7792 7793
/* Single precision floating-point vectors operations */
/* Arithmetic */
A
aurel32 已提交
7794 7795 7796 7797 7798 7799 7800
GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
GEN_SPEFPUOP_ARITH2_64_64(evfssub);
GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
static always_inline void gen_evfsabs (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7801
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
#else
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
#endif
}
static always_inline void gen_evfsnabs (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7814
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
#else
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}
static always_inline void gen_evfsneg (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7827
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7828 7829 7830 7831 7832 7833 7834 7835 7836 7837
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
#else
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}

7838
/* Conversion */
A
aurel32 已提交
7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849
GEN_SPEFPUOP_CONV_64_64(evfscfui);
GEN_SPEFPUOP_CONV_64_64(evfscfsi);
GEN_SPEFPUOP_CONV_64_64(evfscfuf);
GEN_SPEFPUOP_CONV_64_64(evfscfsf);
GEN_SPEFPUOP_CONV_64_64(evfsctui);
GEN_SPEFPUOP_CONV_64_64(evfsctsi);
GEN_SPEFPUOP_CONV_64_64(evfsctuf);
GEN_SPEFPUOP_CONV_64_64(evfsctsf);
GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
GEN_SPEFPUOP_CONV_64_64(evfsctsiz);

7850
/* Comparison */
A
aurel32 已提交
7851 7852 7853 7854 7855 7856
GEN_SPEFPUOP_COMP_64(evfscmpgt);
GEN_SPEFPUOP_COMP_64(evfscmplt);
GEN_SPEFPUOP_COMP_64(evfscmpeq);
GEN_SPEFPUOP_COMP_64(evfststgt);
GEN_SPEFPUOP_COMP_64(evfststlt);
GEN_SPEFPUOP_COMP_64(evfststeq);
7857 7858

/* Opcodes definitions */
7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872
GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7873 7874 7875

/* Single precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
7876 7877 7878 7879 7880 7881 7882
GEN_SPEFPUOP_ARITH2_32_32(efsadd);
GEN_SPEFPUOP_ARITH2_32_32(efssub);
GEN_SPEFPUOP_ARITH2_32_32(efsmul);
GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
static always_inline void gen_efsabs (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7883
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7884 7885 7886 7887 7888 7889 7890
        return;
    }
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
}
static always_inline void gen_efsnabs (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7891
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7892 7893 7894 7895 7896 7897 7898
        return;
    }
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
}
static always_inline void gen_efsneg (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7899
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7900 7901 7902 7903 7904
        return;
    }
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
}

7905
/* Conversion */
A
aurel32 已提交
7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917
GEN_SPEFPUOP_CONV_32_32(efscfui);
GEN_SPEFPUOP_CONV_32_32(efscfsi);
GEN_SPEFPUOP_CONV_32_32(efscfuf);
GEN_SPEFPUOP_CONV_32_32(efscfsf);
GEN_SPEFPUOP_CONV_32_32(efsctui);
GEN_SPEFPUOP_CONV_32_32(efsctsi);
GEN_SPEFPUOP_CONV_32_32(efsctuf);
GEN_SPEFPUOP_CONV_32_32(efsctsf);
GEN_SPEFPUOP_CONV_32_32(efsctuiz);
GEN_SPEFPUOP_CONV_32_32(efsctsiz);
GEN_SPEFPUOP_CONV_32_64(efscfd);

7918
/* Comparison */
A
aurel32 已提交
7919 7920 7921 7922 7923 7924
GEN_SPEFPUOP_COMP_32(efscmpgt);
GEN_SPEFPUOP_COMP_32(efscmplt);
GEN_SPEFPUOP_COMP_32(efscmpeq);
GEN_SPEFPUOP_COMP_32(efststgt);
GEN_SPEFPUOP_COMP_32(efststlt);
GEN_SPEFPUOP_COMP_32(efststeq);
7925 7926

/* Opcodes definitions */
7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7941 7942 7943

/* Double precision floating-point operations */
/* Arithmetic */
A
aurel32 已提交
7944 7945 7946 7947 7948 7949 7950
GEN_SPEFPUOP_ARITH2_64_64(efdadd);
GEN_SPEFPUOP_ARITH2_64_64(efdsub);
GEN_SPEFPUOP_ARITH2_64_64(efdmul);
GEN_SPEFPUOP_ARITH2_64_64(efddiv);
static always_inline void gen_efdabs (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7951
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
#else
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
#endif
}
static always_inline void gen_efdnabs (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7963
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
#else
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}
static always_inline void gen_efdneg (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
A
aurel32 已提交
7975
        gen_exception(ctx, POWERPC_EXCP_APU);
A
aurel32 已提交
7976 7977 7978 7979 7980 7981 7982 7983 7984
        return;
    }
#if defined(TARGET_PPC64)
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
#else
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}

7985
/* Conversion */
A
aurel32 已提交
7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000
GEN_SPEFPUOP_CONV_64_32(efdcfui);
GEN_SPEFPUOP_CONV_64_32(efdcfsi);
GEN_SPEFPUOP_CONV_64_32(efdcfuf);
GEN_SPEFPUOP_CONV_64_32(efdcfsf);
GEN_SPEFPUOP_CONV_32_64(efdctui);
GEN_SPEFPUOP_CONV_32_64(efdctsi);
GEN_SPEFPUOP_CONV_32_64(efdctuf);
GEN_SPEFPUOP_CONV_32_64(efdctsf);
GEN_SPEFPUOP_CONV_32_64(efdctuiz);
GEN_SPEFPUOP_CONV_32_64(efdctsiz);
GEN_SPEFPUOP_CONV_64_32(efdcfs);
GEN_SPEFPUOP_CONV_64_64(efdcfuid);
GEN_SPEFPUOP_CONV_64_64(efdcfsid);
GEN_SPEFPUOP_CONV_64_64(efdctuidz);
GEN_SPEFPUOP_CONV_64_64(efdctsidz);
8001 8002

/* Comparison */
A
aurel32 已提交
8003 8004 8005 8006 8007 8008
GEN_SPEFPUOP_COMP_64(efdcmpgt);
GEN_SPEFPUOP_COMP_64(efdcmplt);
GEN_SPEFPUOP_COMP_64(efdcmpeq);
GEN_SPEFPUOP_COMP_64(efdtstgt);
GEN_SPEFPUOP_COMP_64(efdtstlt);
GEN_SPEFPUOP_COMP_64(efdtsteq);
8009 8010

/* Opcodes definitions */
8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
8027

B
bellard 已提交
8028 8029 8030
/* End opcode list */
GEN_OPCODE_MARK(end);

8031
#include "translate_init.c"
8032
#include "helper_regs.h"
B
bellard 已提交
8033

8034
/*****************************************************************************/
8035
/* Misc PowerPC helpers */
8036 8037 8038
void cpu_dump_state (CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
B
bellard 已提交
8039
{
8040 8041 8042
#define RGPL  4
#define RFPL  4

B
bellard 已提交
8043 8044
    int i;

J
j_mayer 已提交
8045
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
A
aurel32 已提交
8046
                env->nip, env->lr, env->ctr, env->xer);
8047 8048
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
8049
#if !defined(NO_TIMER_DUMP)
J
j_mayer 已提交
8050
    cpu_fprintf(f, "TB %08x %08x "
8051 8052 8053 8054
#if !defined(CONFIG_USER_ONLY)
                "DECR %08x"
#endif
                "\n",
J
j_mayer 已提交
8055
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
8056 8057 8058 8059
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
8060
#endif
8061
    for (i = 0; i < 32; i++) {
8062 8063
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
8064
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
8065
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
8066
            cpu_fprintf(f, "\n");
8067
    }
8068
    cpu_fprintf(f, "CR ");
8069
    for (i = 0; i < 8; i++)
B
bellard 已提交
8070 8071
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
8072 8073 8074 8075 8076 8077 8078 8079
    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 已提交
8080
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
8081
    }
8082
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
8083 8084 8085
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
8086
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
8087
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
8088
            cpu_fprintf(f, "\n");
B
bellard 已提交
8089
    }
8090
    cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
8091
#if !defined(CONFIG_USER_ONLY)
8092
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
8093
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
8094
#endif
B
bellard 已提交
8095

8096 8097
#undef RGPL
#undef RFPL
B
bellard 已提交
8098 8099
}

8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146
void cpu_dump_statistics (CPUState *env, FILE*f,
                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                          int flags)
{
#if defined(DO_PPC_STATISTICS)
    opc_handler_t **t1, **t2, **t3, *handler;
    int op1, op2, op3;

    t1 = env->opcodes;
    for (op1 = 0; op1 < 64; op1++) {
        handler = t1[op1];
        if (is_indirect_opcode(handler)) {
            t2 = ind_table(handler);
            for (op2 = 0; op2 < 32; op2++) {
                handler = t2[op2];
                if (is_indirect_opcode(handler)) {
                    t3 = ind_table(handler);
                    for (op3 = 0; op3 < 32; op3++) {
                        handler = t3[op3];
                        if (handler->count == 0)
                            continue;
                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
                                    "%016llx %lld\n",
                                    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: "
                                "%016llx %lld\n",
                                op1, op2, op1, op2, handler->oname,
                                handler->count, handler->count);
                }
            }
        } else {
            if (handler->count == 0)
                continue;
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016llx %lld\n",
                        op1, op1, handler->oname,
                        handler->count, handler->count);
        }
    }
#endif
}

8147
/*****************************************************************************/
8148 8149 8150
static always_inline void gen_intermediate_code_internal (CPUState *env,
                                                          TranslationBlock *tb,
                                                          int search_pc)
B
bellard 已提交
8151
{
8152
    DisasContext ctx, *ctxp = &ctx;
B
bellard 已提交
8153
    opc_handler_t **table, *handler;
B
bellard 已提交
8154
    target_ulong pc_start;
B
bellard 已提交
8155
    uint16_t *gen_opc_end;
8156
    CPUBreakpoint *bp;
B
bellard 已提交
8157
    int j, lj = -1;
P
pbrook 已提交
8158 8159
    int num_insns;
    int max_insns;
B
bellard 已提交
8160 8161 8162

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
B
bellard 已提交
8163
    ctx.nip = pc_start;
B
bellard 已提交
8164
    ctx.tb = tb;
8165
    ctx.exception = POWERPC_EXCP_NONE;
8166
    ctx.spr_cb = env->spr_cb;
A
aurel32 已提交
8167 8168 8169
    ctx.mem_idx = env->mmu_idx;
    ctx.access_type = -1;
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
8170 8171
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
8172
#endif
B
bellard 已提交
8173
    ctx.fpu_enabled = msr_fp;
8174
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
8175 8176 8177
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
8178 8179 8180 8181
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
8182
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8183
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
8184
    else
8185
        ctx.singlestep_enabled = 0;
8186
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8187 8188 8189
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
8190
#if defined (DO_SINGLE_STEP) && 0
8191 8192 8193
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
8194 8195 8196 8197 8198 8199
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
8200
    /* Set env in case of segfault during code fetch */
8201
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
8202 8203
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8204
                if (bp->pc == ctx.nip) {
A
aurel32 已提交
8205
                    gen_debug_exception(ctxp);
8206 8207 8208 8209
                    break;
                }
            }
        }
8210
        if (unlikely(search_pc)) {
B
bellard 已提交
8211 8212 8213 8214 8215
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
8216
                gen_opc_pc[lj] = ctx.nip;
B
bellard 已提交
8217
                gen_opc_instr_start[lj] = 1;
P
pbrook 已提交
8218
                gen_opc_icount[lj] = num_insns;
B
bellard 已提交
8219 8220
            }
        }
8221 8222 8223
        LOG_DISAS("----------------\n");
        LOG_DISAS("nip=" ADDRX " super=%d ir=%d\n",
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
P
pbrook 已提交
8224 8225
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
A
aurel32 已提交
8226
        if (unlikely(ctx.le_mode)) {
8227 8228 8229
            ctx.opcode = bswap32(ldl_code(ctx.nip));
        } else {
            ctx.opcode = ldl_code(ctx.nip);
8230
        }
8231
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
8232
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
8233
                    opc3(ctx.opcode), little_endian ? "little" : "big");
B
bellard 已提交
8234
        ctx.nip += 4;
8235
        table = env->opcodes;
P
pbrook 已提交
8236
        num_insns++;
B
bellard 已提交
8237 8238 8239 8240 8241 8242 8243 8244 8245 8246
        handler = table[opc1(ctx.opcode)];
        if (is_indirect_opcode(handler)) {
            table = ind_table(handler);
            handler = table[opc2(ctx.opcode)];
            if (is_indirect_opcode(handler)) {
                table = ind_table(handler);
                handler = table[opc3(ctx.opcode)];
            }
        }
        /* Is opcode *REALLY* valid ? */
8247
        if (unlikely(handler->handler == &gen_invalid)) {
8248 8249 8250 8251 8252
            if (qemu_log_enabled()) {
                qemu_log("invalid/unsupported opcode: "
                          "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
                          opc1(ctx.opcode), opc2(ctx.opcode),
                          opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
8253 8254
            } else {
                printf("invalid/unsupported opcode: "
8255
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
B
bellard 已提交
8256
                       opc1(ctx.opcode), opc2(ctx.opcode),
8257
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
8258
            }
8259 8260
        } else {
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
8261 8262 8263 8264 8265 8266
                if (qemu_log_enabled()) {
                    qemu_log("invalid bits: %08x for opcode: "
                              "%02x - %02x - %02x (%08x) " ADDRX "\n",
                              ctx.opcode & handler->inval, opc1(ctx.opcode),
                              opc2(ctx.opcode), opc3(ctx.opcode),
                              ctx.opcode, ctx.nip - 4);
8267 8268
                } else {
                    printf("invalid bits: %08x for opcode: "
8269
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
8270 8271
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
                           opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
8272
                           ctx.opcode, ctx.nip - 4);
8273
                }
A
aurel32 已提交
8274
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
B
bellard 已提交
8275
                break;
B
bellard 已提交
8276 8277
            }
        }
B
bellard 已提交
8278
        (*(handler->handler))(&ctx);
8279 8280 8281
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
8282
        /* Check trace mode exceptions */
8283 8284 8285 8286 8287
        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
                     ctx.exception != POWERPC_SYSCALL &&
                     ctx.exception != POWERPC_EXCP_TRAP &&
                     ctx.exception != POWERPC_EXCP_BRANCH)) {
A
aurel32 已提交
8288
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
8289
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
8290 8291
                            (env->singlestep_enabled) ||
                            num_insns >= max_insns)) {
8292 8293 8294
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
8295
            break;
8296
        }
8297 8298 8299 8300
#if defined (DO_SINGLE_STEP)
        break;
#endif
    }
P
pbrook 已提交
8301 8302
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
8303
    if (ctx.exception == POWERPC_EXCP_NONE) {
8304
        gen_goto_tb(&ctx, 0, ctx.nip);
8305
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
8306
        if (unlikely(env->singlestep_enabled)) {
A
aurel32 已提交
8307
            gen_debug_exception(ctxp);
8308
        }
8309
        /* Generate the return instruction */
B
bellard 已提交
8310
        tcg_gen_exit_tb(0);
8311
    }
P
pbrook 已提交
8312
    gen_icount_end(tb, num_insns);
B
bellard 已提交
8313
    *gen_opc_ptr = INDEX_op_end;
8314
    if (unlikely(search_pc)) {
8315 8316 8317 8318 8319
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
B
bellard 已提交
8320
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
8321
        tb->icount = num_insns;
8322
    }
8323
#if defined(DEBUG_DISAS)
8324 8325
    qemu_log_mask(CPU_LOG_TB_CPU, "---------------- excp: %04x\n", ctx.exception);
    log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
8326
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8327
        int flags;
8328
        flags = env->bfd_mach;
A
aurel32 已提交
8329
        flags |= ctx.le_mode << 16;
8330 8331 8332
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
        log_target_disas(pc_start, ctx.nip - pc_start, flags);
        qemu_log("\n");
8333
    }
B
bellard 已提交
8334 8335 8336
#endif
}

8337
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
8338
{
8339
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
8340 8341
}

8342
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
8343
{
8344
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
8345
}
A
aurel32 已提交
8346 8347 8348 8349 8350 8351

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