translate.c 228.9 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 18 19
 *
 * 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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
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"
A
aurel32 已提交
29
#include "helper.h"
B
bellard 已提交
30
#include "tcg-op.h"
31
#include "qemu-common.h"
B
bellard 已提交
32

33 34 35 36
#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2
#define GDBSTUB_SINGLE_STEP 0x4

37
/* Include definitions for instructions classes and implementations flags */
B
bellard 已提交
38
//#define DO_SINGLE_STEP
39
//#define PPC_DEBUG_DISAS
40
//#define DEBUG_MEMORY_ACCESSES
41
//#define DO_PPC_STATISTICS
42
//#define OPTIMIZE_FPRF_UPDATE
B
bellard 已提交
43

44 45
/*****************************************************************************/
/* Code translation helpers                                                  */
B
bellard 已提交
46

A
aurel32 已提交
47 48
/* global register indexes */
static TCGv cpu_env;
49
static char cpu_reg_names[10*3 + 22*4 /* GPR */
A
aurel32 已提交
50
#if !defined(TARGET_PPC64)
51
    + 10*4 + 22*5 /* SPE GPRh */
A
aurel32 已提交
52
#endif
A
aurel32 已提交
53
    + 10*4 + 22*5 /* FPR */
A
aurel32 已提交
54 55
    + 2*(10*6 + 22*7) /* AVRh, AVRl */
    + 8*5 /* CRF */];
A
aurel32 已提交
56 57 58 59
static TCGv cpu_gpr[32];
#if !defined(TARGET_PPC64)
static TCGv cpu_gprh[32];
#endif
A
aurel32 已提交
60
static TCGv cpu_fpr[32];
61
static TCGv cpu_avrh[32], cpu_avrl[32];
A
aurel32 已提交
62
static TCGv cpu_crf[8];
A
aurel32 已提交
63 64 65 66 67 68 69 70

/* dyngen register indexes */
static TCGv cpu_T[3];
#if defined(TARGET_PPC64)
#define cpu_T64 cpu_T
#else
static TCGv cpu_T64[3];
#endif
A
aurel32 已提交
71
static TCGv cpu_FT[3];
72
static TCGv cpu_AVRh[3], cpu_AVRl[3];
P
pbrook 已提交
73 74 75 76 77

#include "gen-icount.h"

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

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

P
pbrook 已提交
85
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
A
aurel32 已提交
86 87 88 89 90 91 92 93 94 95 96 97
#if TARGET_LONG_BITS > HOST_LONG_BITS
    cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
                                  TCG_AREG0, offsetof(CPUState, t0), "T0");
    cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
                                  TCG_AREG0, offsetof(CPUState, t1), "T1");
    cpu_T[2] = tcg_global_mem_new(TCG_TYPE_TL,
                                  TCG_AREG0, offsetof(CPUState, t2), "T2");
#else
    cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
    cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
    cpu_T[2] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T2");
#endif
A
aurel32 已提交
98 99
#if !defined(TARGET_PPC64)
    cpu_T64[0] = tcg_global_mem_new(TCG_TYPE_I64,
A
aurel32 已提交
100
                                    TCG_AREG0, offsetof(CPUState, t0_64),
A
aurel32 已提交
101 102
                                    "T0_64");
    cpu_T64[1] = tcg_global_mem_new(TCG_TYPE_I64,
A
aurel32 已提交
103
                                    TCG_AREG0, offsetof(CPUState, t1_64),
A
aurel32 已提交
104 105
                                    "T1_64");
    cpu_T64[2] = tcg_global_mem_new(TCG_TYPE_I64,
A
aurel32 已提交
106
                                    TCG_AREG0, offsetof(CPUState, t2_64),
A
aurel32 已提交
107 108
                                    "T2_64");
#endif
A
aurel32 已提交
109 110 111 112 113 114 115 116

    cpu_FT[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                   offsetof(CPUState, ft0), "FT0");
    cpu_FT[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                   offsetof(CPUState, ft1), "FT1");
    cpu_FT[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                   offsetof(CPUState, ft2), "FT2");

117 118 119 120 121 122 123 124 125 126 127 128 129
    cpu_AVRh[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr0.u64[0]), "AVR0H");
    cpu_AVRl[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr0.u64[1]), "AVR0L");
    cpu_AVRh[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr1.u64[0]), "AVR1H");
    cpu_AVRl[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr1.u64[1]), "AVR1L");
    cpu_AVRh[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr2.u64[0]), "AVR2H");
    cpu_AVRl[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                     offsetof(CPUState, avr2.u64[1]), "AVR2L");

A
aurel32 已提交
130
    p = cpu_reg_names;
A
aurel32 已提交
131 132 133 134 135 136 137 138

    for (i = 0; i < 8; i++) {
        sprintf(p, "crf%d", i);
        cpu_crf[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
                                        offsetof(CPUState, crf[i]), p);
        p += 5;
    }

A
aurel32 已提交
139 140 141 142 143 144 145 146 147 148 149
    for (i = 0; i < 32; i++) {
        sprintf(p, "r%d", i);
        cpu_gpr[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
                                        offsetof(CPUState, gpr[i]), p);
        p += (i < 10) ? 3 : 4;
#if !defined(TARGET_PPC64)
        sprintf(p, "r%dH", i);
        cpu_gprh[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
                                         offsetof(CPUState, gprh[i]), p);
        p += (i < 10) ? 4 : 5;
#endif
150

A
aurel32 已提交
151 152 153
        sprintf(p, "fp%d", i);
        cpu_fpr[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                        offsetof(CPUState, fpr[i]), p);
A
aurel32 已提交
154
        p += (i < 10) ? 4 : 5;
A
aurel32 已提交
155

156 157 158 159
        sprintf(p, "avr%dH", i);
        cpu_avrh[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                         offsetof(CPUState, avr[i].u64[0]), p);
        p += (i < 10) ? 6 : 7;
A
aurel32 已提交
160

161 162 163 164
        sprintf(p, "avr%dL", i);
        cpu_avrl[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                         offsetof(CPUState, avr[i].u64[1]), p);
        p += (i < 10) ? 6 : 7;
A
aurel32 已提交
165
    }
A
aurel32 已提交
166 167 168 169 170 171

    /* register helpers */
#undef DEF_HELPER
#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
#include "helper.h"

P
pbrook 已提交
172 173 174
    done_init = 1;
}

175 176 177 178
#if defined(OPTIMIZE_FPRF_UPDATE)
static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
static uint16_t **gen_fprf_ptr;
#endif
B
bellard 已提交
179

180 181 182 183 184 185 186
#define GEN16(func, NAME)                                                     \
static GenOpFunc *NAME ## _table [16] = {                                     \
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
};                                                                            \
187
static always_inline void func (int n)                                        \
188 189
{                                                                             \
    NAME ## _table[n]();                                                      \
190 191
}

192
#define GEN32(func, NAME)                                                     \
193 194 195 196 197 198 199 200 201 202
static GenOpFunc *NAME ## _table [32] = {                                     \
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
};                                                                            \
203
static always_inline void func (int n)                                        \
204 205 206 207
{                                                                             \
    NAME ## _table[n]();                                                      \
}

B
bellard 已提交
208 209 210
/* internal defines */
typedef struct DisasContext {
    struct TranslationBlock *tb;
B
bellard 已提交
211
    target_ulong nip;
B
bellard 已提交
212
    uint32_t opcode;
213
    uint32_t exception;
B
bellard 已提交
214 215 216
    /* Routine used to access memory */
    int mem_idx;
    /* Translation flags */
217
#if !defined(CONFIG_USER_ONLY)
B
bellard 已提交
218
    int supervisor;
219 220 221
#endif
#if defined(TARGET_PPC64)
    int sf_mode;
222
#endif
B
bellard 已提交
223
    int fpu_enabled;
224
    int altivec_enabled;
225
    int spe_enabled;
226
    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
227
    int singlestep_enabled;
228
    int dcache_line_size;
B
bellard 已提交
229 230
} DisasContext;

231
struct opc_handler_t {
B
bellard 已提交
232 233
    /* invalid bits */
    uint32_t inval;
234
    /* instruction type */
235
    uint64_t type;
B
bellard 已提交
236 237
    /* handler */
    void (*handler)(DisasContext *ctx);
238
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
239
    const unsigned char *oname;
240 241
#endif
#if defined(DO_PPC_STATISTICS)
242 243
    uint64_t count;
#endif
244
};
B
bellard 已提交
245

246
static always_inline void gen_set_Rc0 (DisasContext *ctx)
247
{
248 249 250 251 252 253
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_cmpi_64(0);
    else
#endif
        gen_op_cmpi(0);
254 255 256
    gen_op_set_Rc0();
}

257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
static always_inline void gen_reset_fpstatus (void)
{
#ifdef CONFIG_SOFTFLOAT
    gen_op_reset_fpstatus();
#endif
}

static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
{
    if (set_fprf != 0) {
        /* This case might be optimized later */
#if defined(OPTIMIZE_FPRF_UPDATE)
        *gen_fprf_ptr++ = gen_opc_ptr;
#endif
        gen_op_compute_fprf(1);
        if (unlikely(set_rc))
A
aurel32 已提交
273
            tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
274 275 276 277
        gen_op_float_check_status();
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
        gen_op_compute_fprf(0);
A
aurel32 已提交
278
        tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
        if (set_fprf)
            gen_op_float_check_status();
    }
}

static always_inline void gen_optimize_fprf (void)
{
#if defined(OPTIMIZE_FPRF_UPDATE)
    uint16_t **ptr;

    for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
        *ptr = INDEX_op_nop1;
    gen_fprf_ptr = gen_fprf_buf;
#endif
}

295
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
296 297 298
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
A
aurel32 已提交
299
        gen_op_update_nip_64(nip >> 32, nip);
300 301
    else
#endif
A
aurel32 已提交
302
        gen_op_update_nip(nip);
303 304
}

305
#define GEN_EXCP(ctx, excp, error)                                            \
B
bellard 已提交
306
do {                                                                          \
307
    if ((ctx)->exception == POWERPC_EXCP_NONE) {                              \
308
        gen_update_nip(ctx, (ctx)->nip);                                      \
309 310 311
    }                                                                         \
    gen_op_raise_exception_err((excp), (error));                              \
    ctx->exception = (excp);                                                  \
B
bellard 已提交
312 313
} while (0)

314 315 316
#define GEN_EXCP_INVAL(ctx)                                                   \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
317

318 319 320
#define GEN_EXCP_PRIVOPC(ctx)                                                 \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
321

322 323 324 325 326 327 328 329 330
#define GEN_EXCP_PRIVREG(ctx)                                                 \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)

#define GEN_EXCP_NO_FP(ctx)                                                   \
GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)

#define GEN_EXCP_NO_AP(ctx)                                                   \
GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
331

332 333 334
#define GEN_EXCP_NO_VR(ctx)                                                   \
GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)

335
/* Stop translation */
336
static always_inline void GEN_STOP (DisasContext *ctx)
337
{
338
    gen_update_nip(ctx, ctx->nip);
339
    ctx->exception = POWERPC_EXCP_STOP;
340 341
}

342
/* No need to update nip here, as execution flow will change */
343
static always_inline void GEN_SYNC (DisasContext *ctx)
344
{
345
    ctx->exception = POWERPC_EXCP_SYNC;
346 347
}

B
bellard 已提交
348 349 350 351 352
#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)

353 354 355 356 357
#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 已提交
358 359
typedef struct opcode_t {
    unsigned char opc1, opc2, opc3;
T
ths 已提交
360
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
361 362 363 364
    unsigned char pad[5];
#else
    unsigned char pad[1];
#endif
B
bellard 已提交
365
    opc_handler_t handler;
366
    const unsigned char *oname;
B
bellard 已提交
367 368
} opcode_t;

369
/*****************************************************************************/
B
bellard 已提交
370 371
/***                           Instruction decoding                        ***/
#define EXTRACT_HELPER(name, shift, nb)                                       \
372
static always_inline uint32_t name (uint32_t opcode)                          \
B
bellard 已提交
373 374 375 376 377
{                                                                             \
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
}

#define EXTRACT_SHELPER(name, shift, nb)                                      \
378
static always_inline int32_t name (uint32_t opcode)                           \
B
bellard 已提交
379
{                                                                             \
380
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
B
bellard 已提交
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
}

/* 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 */
408
EXTRACT_HELPER(_SPR, 11, 10);
409
static always_inline uint32_t SPR (uint32_t opcode)
410 411 412 413 414
{
    uint32_t sprn = _SPR(opcode);

    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
}
B
bellard 已提交
415 416 417 418 419 420 421 422 423 424 425 426 427 428
/***                              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);
/* Bit count */
EXTRACT_HELPER(NB, 11, 5);
/* Shift count */
EXTRACT_HELPER(SH, 11, 5);
/* Mask start */
EXTRACT_HELPER(MB, 6, 5);
/* Mask end */
EXTRACT_HELPER(ME, 1, 5);
B
bellard 已提交
429 430
/* Trap operand */
EXTRACT_HELPER(TO, 21, 5);
B
bellard 已提交
431 432 433 434

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

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

446
static always_inline uint32_t BD (uint32_t opcode)
B
bellard 已提交
447 448 449 450 451 452 453 454 455 456 457 458
{
    return (opcode >> 0) & 0xFFFC;
}

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

/* Create a mask between <start> and <end> bits */
459
static always_inline target_ulong MASK (uint32_t start, uint32_t end)
B
bellard 已提交
460
{
461
    target_ulong ret;
B
bellard 已提交
462

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

    return ret;
}

486 487 488
/*****************************************************************************/
/* PowerPC Instructions types definitions                                    */
enum {
489
    PPC_NONE           = 0x0000000000000000ULL,
490
    /* PowerPC base instructions set                                         */
491 492
    PPC_INSNS_BASE     = 0x0000000000000001ULL,
    /*   integer operations instructions                                     */
493
#define PPC_INTEGER PPC_INSNS_BASE
494
    /*   flow control instructions                                           */
495
#define PPC_FLOW    PPC_INSNS_BASE
496
    /*   virtual memory instructions                                         */
497
#define PPC_MEM     PPC_INSNS_BASE
498
    /*   ld/st with reservation instructions                                 */
499
#define PPC_RES     PPC_INSNS_BASE
500
    /*   spr/msr access instructions                                         */
501
#define PPC_MISC    PPC_INSNS_BASE
502 503
    /* Deprecated instruction sets                                           */
    /*   Original POWER instruction set                                      */
504
    PPC_POWER          = 0x0000000000000002ULL,
505
    /*   POWER2 instruction set extension                                    */
506
    PPC_POWER2         = 0x0000000000000004ULL,
507
    /*   Power RTC support                                                   */
508
    PPC_POWER_RTC      = 0x0000000000000008ULL,
509
    /*   Power-to-PowerPC bridge (601)                                       */
510
    PPC_POWER_BR       = 0x0000000000000010ULL,
511
    /* 64 bits PowerPC instruction set                                       */
512
    PPC_64B            = 0x0000000000000020ULL,
513
    /*   New 64 bits extensions (PowerPC 2.0x)                               */
514
    PPC_64BX           = 0x0000000000000040ULL,
515
    /*   64 bits hypervisor extensions                                       */
516
    PPC_64H            = 0x0000000000000080ULL,
517
    /*   New wait instruction (PowerPC 2.0x)                                 */
518
    PPC_WAIT           = 0x0000000000000100ULL,
519
    /*   Time base mftb instruction                                          */
520
    PPC_MFTB           = 0x0000000000000200ULL,
521 522 523

    /* Fixed-point unit extensions                                           */
    /*   PowerPC 602 specific                                                */
524
    PPC_602_SPEC       = 0x0000000000000400ULL,
525 526 527 528 529 530
    /*   isel instruction                                                    */
    PPC_ISEL           = 0x0000000000000800ULL,
    /*   popcntb instruction                                                 */
    PPC_POPCNTB        = 0x0000000000001000ULL,
    /*   string load / store                                                 */
    PPC_STRING         = 0x0000000000002000ULL,
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547

    /* 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                                          */
548
    PPC_SPE            = 0x0000000002000000ULL,
549
    /*   PowerPC 2.03 SPE floating-point extension                           */
550
    PPC_SPEFPU         = 0x0000000004000000ULL,
551

552
    /* Optional memory control instructions                                  */
553 554 555 556 557 558 559 560 561
    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                                            */
562
    PPC_CACHE          = 0x0000000200000000ULL,
563
    /*   icbi instruction                                                    */
564
    PPC_CACHE_ICBI     = 0x0000000400000000ULL,
565
    /*   dcbz instruction with fixed cache line size                         */
566
    PPC_CACHE_DCBZ     = 0x0000000800000000ULL,
567
    /*   dcbz instruction with tunable cache line size                       */
568
    PPC_CACHE_DCBZT    = 0x0000001000000000ULL,
569
    /*   dcba instruction                                                    */
570 571 572
    PPC_CACHE_DCBA     = 0x0000002000000000ULL,
    /*   Freescale cache locking instructions                                */
    PPC_CACHE_LOCK     = 0x0000004000000000ULL,
573 574 575

    /* MMU related extensions                                                */
    /*   external control instructions                                       */
576
    PPC_EXTERN         = 0x0000010000000000ULL,
577
    /*   segment register access instructions                                */
578
    PPC_SEGMENT        = 0x0000020000000000ULL,
579
    /*   PowerPC 6xx TLB management instructions                             */
580
    PPC_6xx_TLB        = 0x0000040000000000ULL,
581
    /* PowerPC 74xx TLB management instructions                              */
582
    PPC_74xx_TLB       = 0x0000080000000000ULL,
583
    /*   PowerPC 40x TLB management instructions                             */
584
    PPC_40x_TLB        = 0x0000100000000000ULL,
585
    /*   segment register access instructions for PowerPC 64 "bridge"        */
586
    PPC_SEGMENT_64B    = 0x0000200000000000ULL,
587
    /*   SLB management                                                      */
588
    PPC_SLBI           = 0x0000400000000000ULL,
589

590
    /* Embedded PowerPC dedicated instructions                               */
591
    PPC_WRTEE          = 0x0001000000000000ULL,
592
    /* PowerPC 40x exception model                                           */
593
    PPC_40x_EXCP       = 0x0002000000000000ULL,
594
    /* PowerPC 405 Mac instructions                                          */
595
    PPC_405_MAC        = 0x0004000000000000ULL,
596
    /* PowerPC 440 specific instructions                                     */
597
    PPC_440_SPEC       = 0x0008000000000000ULL,
598
    /* BookE (embedded) PowerPC specification                                */
599 600 601 602 603 604 605
    PPC_BOOKE          = 0x0010000000000000ULL,
    /* mfapidi instruction                                                   */
    PPC_MFAPIDI        = 0x0020000000000000ULL,
    /* tlbiva instruction                                                    */
    PPC_TLBIVA         = 0x0040000000000000ULL,
    /* tlbivax instruction                                                   */
    PPC_TLBIVAX        = 0x0080000000000000ULL,
606
    /* PowerPC 4xx dedicated instructions                                    */
607
    PPC_4xx_COMMON     = 0x0100000000000000ULL,
608
    /* PowerPC 40x ibct instructions                                         */
609
    PPC_40x_ICBT       = 0x0200000000000000ULL,
610
    /* rfmci is not implemented in all BookE PowerPC                         */
611 612 613 614 615 616 617
    PPC_RFMCI          = 0x0400000000000000ULL,
    /* rfdi instruction                                                      */
    PPC_RFDI           = 0x0800000000000000ULL,
    /* DCR accesses                                                          */
    PPC_DCR            = 0x1000000000000000ULL,
    /* DCR extended accesse                                                  */
    PPC_DCRX           = 0x2000000000000000ULL,
618
    /* user-mode DCR access, implemented in PowerPC 460                      */
619
    PPC_DCRUX          = 0x4000000000000000ULL,
620 621 622 623
};

/*****************************************************************************/
/* PowerPC instructions table                                                */
624 625 626 627 628
#if HOST_LONG_BITS == 64
#define OPC_ALIGN 8
#else
#define OPC_ALIGN 4
#endif
B
bellard 已提交
629
#if defined(__APPLE__)
630
#define OPCODES_SECTION                                                       \
631
    __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
632
#else
633
#define OPCODES_SECTION                                                       \
634
    __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
635 636
#endif

637
#if defined(DO_PPC_STATISTICS)
B
bellard 已提交
638
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
639
OPCODES_SECTION opcode_t opc_##name = {                                       \
B
bellard 已提交
640 641 642
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
643
    .pad  = { 0, },                                                           \
B
bellard 已提交
644 645
    .handler = {                                                              \
        .inval   = invl,                                                      \
646
        .type = _typ,                                                         \
B
bellard 已提交
647
        .handler = &gen_##name,                                               \
648
        .oname = stringify(name),                                             \
B
bellard 已提交
649
    },                                                                        \
650
    .oname = stringify(name),                                                 \
B
bellard 已提交
651
}
652 653 654 655 656 657 658 659 660 661 662 663 664 665
#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,                                                            \
}
666 667 668 669 670 671 672 673 674 675 676 677 678 679
#else
#define GEN_OPCODE(name, 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 = stringify(name),                                                 \
}
680 681 682 683 684 685 686 687 688 689 690 691 692
#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,                                                            \
}
693
#endif
B
bellard 已提交
694 695

#define GEN_OPCODE_MARK(name)                                                 \
696
OPCODES_SECTION opcode_t opc_##name = {                                       \
B
bellard 已提交
697 698 699
    .opc1 = 0xFF,                                                             \
    .opc2 = 0xFF,                                                             \
    .opc3 = 0xFF,                                                             \
700
    .pad  = { 0, },                                                           \
B
bellard 已提交
701 702
    .handler = {                                                              \
        .inval   = 0x00000000,                                                \
703
        .type = 0x00,                                                         \
B
bellard 已提交
704 705
        .handler = NULL,                                                      \
    },                                                                        \
706
    .oname = stringify(name),                                                 \
B
bellard 已提交
707 708 709 710 711 712
}

/* Start opcode list */
GEN_OPCODE_MARK(start);

/* Invalid instruction */
713 714
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
{
715
    GEN_EXCP_INVAL(ctx);
716 717
}

B
bellard 已提交
718 719
static opc_handler_t invalid_handler = {
    .inval   = 0xFFFFFFFF,
720
    .type    = PPC_NONE,
B
bellard 已提交
721 722 723 724
    .handler = gen_invalid,
};

/***                           Integer arithmetic                          ***/
725 726
#define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval, type)                 \
GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
B
bellard 已提交
727
{                                                                             \
A
aurel32 已提交
728 729
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);                       \
B
bellard 已提交
730
    gen_op_##name();                                                          \
A
aurel32 已提交
731
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);                       \
732 733
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
734 735
}

736 737
#define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval, type)               \
GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
B
bellard 已提交
738
{                                                                             \
A
aurel32 已提交
739 740
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);                       \
B
bellard 已提交
741
    gen_op_##name();                                                          \
A
aurel32 已提交
742
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);                       \
743 744
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
745 746
}

747 748
#define __GEN_INT_ARITH1(name, opc1, opc2, opc3, type)                        \
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
B
bellard 已提交
749
{                                                                             \
A
aurel32 已提交
750
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
B
bellard 已提交
751
    gen_op_##name();                                                          \
A
aurel32 已提交
752
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);                       \
753 754
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
755
}
756 757
#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3, type)                      \
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
B
bellard 已提交
758
{                                                                             \
A
aurel32 已提交
759
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
B
bellard 已提交
760
    gen_op_##name();                                                          \
A
aurel32 已提交
761
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);                       \
762 763
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
764 765 766
}

/* Two operands arithmetic functions */
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
#define GEN_INT_ARITH2(name, opc1, opc2, opc3, type)                          \
__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000, type)                    \
__GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)

/* Two operands arithmetic functions with no overflow allowed */
#define GEN_INT_ARITHN(name, opc1, opc2, opc3, type)                          \
__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400, type)

/* One operand arithmetic functions */
#define GEN_INT_ARITH1(name, opc1, opc2, opc3, type)                          \
__GEN_INT_ARITH1(name, opc1, opc2, opc3, type)                                \
__GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10, type)

#if defined(TARGET_PPC64)
#define __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, inval, type)              \
GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
{                                                                             \
A
aurel32 已提交
784 785
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);                       \
786 787 788 789
    if (ctx->sf_mode)                                                         \
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
A
aurel32 已提交
790
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);                       \
791 792 793 794 795 796 797
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
}

#define __GEN_INT_ARITH2_O_64(name, opc1, opc2, opc3, inval, type)            \
GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
{                                                                             \
A
aurel32 已提交
798 799
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);                       \
800 801 802 803
    if (ctx->sf_mode)                                                         \
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
A
aurel32 已提交
804
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);                       \
805 806 807 808 809 810 811
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
}

#define __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type)                     \
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
{                                                                             \
A
aurel32 已提交
812
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
813 814 815 816
    if (ctx->sf_mode)                                                         \
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
A
aurel32 已提交
817
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);                       \
818 819 820 821 822 823
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
}
#define __GEN_INT_ARITH1_O_64(name, opc1, opc2, opc3, type)                   \
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
{                                                                             \
A
aurel32 已提交
824
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
825 826 827 828
    if (ctx->sf_mode)                                                         \
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
A
aurel32 已提交
829
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);                       \
830 831 832 833 834 835 836 837
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
}

/* Two operands arithmetic functions */
#define GEN_INT_ARITH2_64(name, opc1, opc2, opc3, type)                       \
__GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000000, type)                 \
__GEN_INT_ARITH2_O_64(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
B
bellard 已提交
838 839

/* Two operands arithmetic functions with no overflow allowed */
840 841
#define GEN_INT_ARITHN_64(name, opc1, opc2, opc3, type)                       \
__GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000400, type)
B
bellard 已提交
842 843

/* One operand arithmetic functions */
844 845 846 847 848 849 850 851
#define GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type)                       \
__GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type)                             \
__GEN_INT_ARITH1_O_64(name##o, opc1, opc2, opc3 | 0x10, type)
#else
#define GEN_INT_ARITH2_64 GEN_INT_ARITH2
#define GEN_INT_ARITHN_64 GEN_INT_ARITHN
#define GEN_INT_ARITH1_64 GEN_INT_ARITH1
#endif
B
bellard 已提交
852 853

/* add    add.    addo    addo.    */
854
static always_inline void gen_op_addo (void)
855
{
856
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
857 858 859 860 861
    gen_op_add();
    gen_op_check_addo();
}
#if defined(TARGET_PPC64)
#define gen_op_add_64 gen_op_add
862
static always_inline void gen_op_addo_64 (void)
863
{
864
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
865 866 867 868 869
    gen_op_add();
    gen_op_check_addo_64();
}
#endif
GEN_INT_ARITH2_64 (add,    0x1F, 0x0A, 0x08, PPC_INTEGER);
B
bellard 已提交
870
/* addc   addc.   addco   addco.   */
871
static always_inline void gen_op_addc (void)
872
{
873
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
874 875 876
    gen_op_add();
    gen_op_check_addc();
}
877
static always_inline void gen_op_addco (void)
878
{
879
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
880 881 882 883 884
    gen_op_add();
    gen_op_check_addc();
    gen_op_check_addo();
}
#if defined(TARGET_PPC64)
885
static always_inline void gen_op_addc_64 (void)
886
{
887
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
888 889 890
    gen_op_add();
    gen_op_check_addc_64();
}
891
static always_inline void gen_op_addco_64 (void)
892
{
893
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
894 895 896 897 898 899
    gen_op_add();
    gen_op_check_addc_64();
    gen_op_check_addo_64();
}
#endif
GEN_INT_ARITH2_64 (addc,   0x1F, 0x0A, 0x00, PPC_INTEGER);
B
bellard 已提交
900
/* adde   adde.   addeo   addeo.   */
901
static always_inline void gen_op_addeo (void)
902
{
903
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
904 905 906 907
    gen_op_adde();
    gen_op_check_addo();
}
#if defined(TARGET_PPC64)
908
static always_inline void gen_op_addeo_64 (void)
909
{
910
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
911 912 913 914 915
    gen_op_adde_64();
    gen_op_check_addo_64();
}
#endif
GEN_INT_ARITH2_64 (adde,   0x1F, 0x0A, 0x04, PPC_INTEGER);
B
bellard 已提交
916
/* addme  addme.  addmeo  addmeo.  */
917
static always_inline void gen_op_addme (void)
918
{
919
    tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
920 921 922
    gen_op_add_me();
}
#if defined(TARGET_PPC64)
923
static always_inline void gen_op_addme_64 (void)
924
{
925
    tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
926 927 928 929
    gen_op_add_me_64();
}
#endif
GEN_INT_ARITH1_64 (addme,  0x1F, 0x0A, 0x07, PPC_INTEGER);
B
bellard 已提交
930
/* addze  addze.  addzeo  addzeo.  */
931
static always_inline void gen_op_addze (void)
932
{
933
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
934 935 936
    gen_op_add_ze();
    gen_op_check_addc();
}
937
static always_inline void gen_op_addzeo (void)
938
{
939
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
940 941 942 943 944
    gen_op_add_ze();
    gen_op_check_addc();
    gen_op_check_addo();
}
#if defined(TARGET_PPC64)
945
static always_inline void gen_op_addze_64 (void)
946
{
947
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
948 949 950
    gen_op_add_ze();
    gen_op_check_addc_64();
}
951
static always_inline void gen_op_addzeo_64 (void)
952
{
953
    tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
954 955 956 957 958 959
    gen_op_add_ze();
    gen_op_check_addc_64();
    gen_op_check_addo_64();
}
#endif
GEN_INT_ARITH1_64 (addze,  0x1F, 0x0A, 0x06, PPC_INTEGER);
B
bellard 已提交
960
/* divw   divw.   divwo   divwo.   */
961
GEN_INT_ARITH2 (divw,   0x1F, 0x0B, 0x0F, PPC_INTEGER);
B
bellard 已提交
962
/* divwu  divwu.  divwuo  divwuo.  */
963
GEN_INT_ARITH2 (divwu,  0x1F, 0x0B, 0x0E, PPC_INTEGER);
B
bellard 已提交
964
/* mulhw  mulhw.                   */
965
GEN_INT_ARITHN (mulhw,  0x1F, 0x0B, 0x02, PPC_INTEGER);
B
bellard 已提交
966
/* mulhwu mulhwu.                  */
967
GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00, PPC_INTEGER);
B
bellard 已提交
968
/* mullw  mullw.  mullwo  mullwo.  */
969
GEN_INT_ARITH2 (mullw,  0x1F, 0x0B, 0x07, PPC_INTEGER);
B
bellard 已提交
970
/* neg    neg.    nego    nego.    */
971
GEN_INT_ARITH1_64 (neg,    0x1F, 0x08, 0x03, PPC_INTEGER);
B
bellard 已提交
972
/* subf   subf.   subfo   subfo.   */
973
static always_inline void gen_op_subfo (void)
974
{
A
aurel32 已提交
975
    tcg_gen_not_tl(cpu_T[2], cpu_T[0]);
976
    gen_op_subf();
977
    gen_op_check_addo();
978 979 980
}
#if defined(TARGET_PPC64)
#define gen_op_subf_64 gen_op_subf
981
static always_inline void gen_op_subfo_64 (void)
982
{
A
aurel32 已提交
983
    tcg_gen_not_i64(cpu_T[2], cpu_T[0]);
984
    gen_op_subf();
985
    gen_op_check_addo_64();
986 987 988
}
#endif
GEN_INT_ARITH2_64 (subf,   0x1F, 0x08, 0x01, PPC_INTEGER);
B
bellard 已提交
989
/* subfc  subfc.  subfco  subfco.  */
990
static always_inline void gen_op_subfc (void)
991 992 993 994
{
    gen_op_subf();
    gen_op_check_subfc();
}
995
static always_inline void gen_op_subfco (void)
996
{
A
aurel32 已提交
997
    tcg_gen_not_tl(cpu_T[2], cpu_T[0]);
998 999
    gen_op_subf();
    gen_op_check_subfc();
1000
    gen_op_check_addo();
1001 1002
}
#if defined(TARGET_PPC64)
1003
static always_inline void gen_op_subfc_64 (void)
1004 1005 1006 1007
{
    gen_op_subf();
    gen_op_check_subfc_64();
}
1008
static always_inline void gen_op_subfco_64 (void)
1009
{
A
aurel32 已提交
1010
    tcg_gen_not_i64(cpu_T[2], cpu_T[0]);
1011 1012
    gen_op_subf();
    gen_op_check_subfc_64();
1013
    gen_op_check_addo_64();
1014 1015 1016
}
#endif
GEN_INT_ARITH2_64 (subfc,  0x1F, 0x08, 0x00, PPC_INTEGER);
B
bellard 已提交
1017
/* subfe  subfe.  subfeo  subfeo.  */
1018
static always_inline void gen_op_subfeo (void)
1019
{
A
aurel32 已提交
1020
    tcg_gen_not_tl(cpu_T[2], cpu_T[0]);
1021
    gen_op_subfe();
1022
    gen_op_check_addo();
1023 1024 1025
}
#if defined(TARGET_PPC64)
#define gen_op_subfe_64 gen_op_subfe
1026
static always_inline void gen_op_subfeo_64 (void)
1027
{
A
aurel32 已提交
1028
    tcg_gen_not_i64(cpu_T[2], cpu_T[0]);
1029
    gen_op_subfe_64();
1030
    gen_op_check_addo_64();
1031 1032 1033
}
#endif
GEN_INT_ARITH2_64 (subfe,  0x1F, 0x08, 0x04, PPC_INTEGER);
B
bellard 已提交
1034
/* subfme subfme. subfmeo subfmeo. */
1035
GEN_INT_ARITH1_64 (subfme, 0x1F, 0x08, 0x07, PPC_INTEGER);
B
bellard 已提交
1036
/* subfze subfze. subfzeo subfzeo. */
1037
GEN_INT_ARITH1_64 (subfze, 0x1F, 0x08, 0x06, PPC_INTEGER);
B
bellard 已提交
1038 1039 1040
/* addi */
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1041
    target_long simm = SIMM(ctx->opcode);
B
bellard 已提交
1042 1043

    if (rA(ctx->opcode) == 0) {
1044
        /* li case */
A
aurel32 已提交
1045
        tcg_gen_movi_tl(cpu_T[0], simm);
B
bellard 已提交
1046
    } else {
A
aurel32 已提交
1047
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1048 1049
        if (likely(simm != 0))
            gen_op_addi(simm);
B
bellard 已提交
1050
    }
A
aurel32 已提交
1051
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
1052 1053 1054 1055
}
/* addic */
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1056 1057
    target_long simm = SIMM(ctx->opcode);

A
aurel32 已提交
1058
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1059
    if (likely(simm != 0)) {
1060
        tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
1061 1062 1063 1064 1065 1066 1067
        gen_op_addi(simm);
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_check_addc_64();
        else
#endif
            gen_op_check_addc();
J
j_mayer 已提交
1068 1069
    } else {
        gen_op_clear_xer_ca();
1070
    }
A
aurel32 已提交
1071
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
1072 1073
}
/* addic. */
1074
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1075
{
1076 1077
    target_long simm = SIMM(ctx->opcode);

A
aurel32 已提交
1078
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1079
    if (likely(simm != 0)) {
1080
        tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
1081 1082 1083 1084 1085 1086 1087
        gen_op_addi(simm);
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_check_addc_64();
        else
#endif
            gen_op_check_addc();
J
j_mayer 已提交
1088 1089
    } else {
        gen_op_clear_xer_ca();
1090
    }
A
aurel32 已提交
1091
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1092
    gen_set_Rc0(ctx);
B
bellard 已提交
1093 1094 1095 1096
}
/* addis */
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1097
    target_long simm = SIMM(ctx->opcode);
B
bellard 已提交
1098 1099

    if (rA(ctx->opcode) == 0) {
1100
        /* lis case */
A
aurel32 已提交
1101
        tcg_gen_movi_tl(cpu_T[0], simm << 16);
B
bellard 已提交
1102
    } else {
A
aurel32 已提交
1103
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1104 1105
        if (likely(simm != 0))
            gen_op_addi(simm << 16);
B
bellard 已提交
1106
    }
A
aurel32 已提交
1107
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
1108 1109 1110 1111
}
/* mulli */
GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
A
aurel32 已提交
1112
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1113
    gen_op_mulli(SIMM(ctx->opcode));
A
aurel32 已提交
1114
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
1115 1116 1117 1118
}
/* subfic */
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
A
aurel32 已提交
1119
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1120 1121 1122 1123 1124 1125
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_subfic_64(SIMM(ctx->opcode));
    else
#endif
        gen_op_subfic(SIMM(ctx->opcode));
A
aurel32 已提交
1126
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
1127 1128
}

1129 1130
#if defined(TARGET_PPC64)
/* mulhd  mulhd.                   */
1131
GEN_INT_ARITHN (mulhd,  0x1F, 0x09, 0x02, PPC_64B);
1132
/* mulhdu mulhdu.                  */
1133
GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_64B);
1134
/* mulld  mulld.  mulldo  mulldo.  */
1135
GEN_INT_ARITH2 (mulld,  0x1F, 0x09, 0x07, PPC_64B);
1136
/* divd   divd.   divdo   divdo.   */
1137
GEN_INT_ARITH2 (divd,   0x1F, 0x09, 0x0F, PPC_64B);
1138
/* divdu  divdu.  divduo  divduo.  */
1139
GEN_INT_ARITH2 (divdu,  0x1F, 0x09, 0x0E, PPC_64B);
1140 1141
#endif

B
bellard 已提交
1142
/***                           Integer comparison                          ***/
1143 1144 1145 1146
#if defined(TARGET_PPC64)
#define GEN_CMP(name, opc, type)                                              \
GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type)                          \
{                                                                             \
A
aurel32 已提交
1147 1148
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);                       \
1149
    if (ctx->sf_mode && (ctx->opcode & 0x00200000))                           \
1150 1151 1152
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
A
aurel32 已提交
1153
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);              \
1154 1155 1156 1157
}
#else
#define GEN_CMP(name, opc, type)                                              \
GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type)                          \
B
bellard 已提交
1158
{                                                                             \
A
aurel32 已提交
1159 1160
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);                       \
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);                       \
B
bellard 已提交
1161
    gen_op_##name();                                                          \
A
aurel32 已提交
1162
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);              \
B
bellard 已提交
1163
}
1164
#endif
B
bellard 已提交
1165 1166

/* cmp */
1167
GEN_CMP(cmp, 0x00, PPC_INTEGER);
B
bellard 已提交
1168 1169 1170
/* cmpi */
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
{
A
aurel32 已提交
1171
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1172
#if defined(TARGET_PPC64)
1173
    if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1174 1175 1176 1177
        gen_op_cmpi_64(SIMM(ctx->opcode));
    else
#endif
        gen_op_cmpi(SIMM(ctx->opcode));
A
aurel32 已提交
1178
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
B
bellard 已提交
1179 1180
}
/* cmpl */
1181
GEN_CMP(cmpl, 0x01, PPC_INTEGER);
B
bellard 已提交
1182 1183 1184
/* cmpli */
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
{
A
aurel32 已提交
1185
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1186
#if defined(TARGET_PPC64)
1187
    if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1188 1189 1190 1191
        gen_op_cmpli_64(UIMM(ctx->opcode));
    else
#endif
        gen_op_cmpli(UIMM(ctx->opcode));
A
aurel32 已提交
1192
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
B
bellard 已提交
1193 1194
}

1195
/* isel (PowerPC 2.03 specification) */
A
aurel32 已提交
1196
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
1197 1198 1199 1200 1201
{
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;

    if (rA(ctx->opcode) == 0) {
A
aurel32 已提交
1202
        tcg_gen_movi_tl(cpu_T[0], 0);
1203
    } else {
A
aurel32 已提交
1204
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1205
    }
A
aurel32 已提交
1206
    tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
1207
    mask = 1 << (3 - (bi & 0x03));
A
aurel32 已提交
1208
    tcg_gen_mov_i32(cpu_T[0], cpu_crf[bi >> 2]);
1209 1210
    gen_op_test_true(mask);
    gen_op_isel();
A
aurel32 已提交
1211
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1212 1213
}

B
bellard 已提交
1214
/***                            Integer logical                            ***/
1215 1216
#define __GEN_LOGICAL2(name, opc2, opc3, type)                                \
GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type)                         \
B
bellard 已提交
1217
{                                                                             \
A
aurel32 已提交
1218 1219
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);                       \
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);                       \
B
bellard 已提交
1220
    gen_op_##name();                                                          \
A
aurel32 已提交
1221
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
1222 1223
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
1224
}
1225 1226
#define GEN_LOGICAL2(name, opc, type)                                         \
__GEN_LOGICAL2(name, 0x1C, opc, type)
B
bellard 已提交
1227

1228 1229
#define GEN_LOGICAL1(name, opc, type)                                         \
GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)                          \
B
bellard 已提交
1230
{                                                                             \
A
aurel32 已提交
1231
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);                       \
B
bellard 已提交
1232
    gen_op_##name();                                                          \
A
aurel32 已提交
1233
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
1234 1235
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
1236 1237 1238
}

/* and & and. */
1239
GEN_LOGICAL2(and, 0x00, PPC_INTEGER);
B
bellard 已提交
1240
/* andc & andc. */
1241
GEN_LOGICAL2(andc, 0x01, PPC_INTEGER);
B
bellard 已提交
1242
/* andi. */
1243
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1244
{
A
aurel32 已提交
1245
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1246
    gen_op_andi_T0(UIMM(ctx->opcode));
A
aurel32 已提交
1247
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1248
    gen_set_Rc0(ctx);
B
bellard 已提交
1249 1250
}
/* andis. */
1251
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1252
{
A
aurel32 已提交
1253
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1254
    gen_op_andi_T0(UIMM(ctx->opcode) << 16);
A
aurel32 已提交
1255
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1256
    gen_set_Rc0(ctx);
B
bellard 已提交
1257 1258 1259
}

/* cntlzw */
1260
GEN_LOGICAL1(cntlzw, 0x00, PPC_INTEGER);
B
bellard 已提交
1261
/* eqv & eqv. */
1262
GEN_LOGICAL2(eqv, 0x08, PPC_INTEGER);
B
bellard 已提交
1263
/* extsb & extsb. */
1264
GEN_LOGICAL1(extsb, 0x1D, PPC_INTEGER);
B
bellard 已提交
1265
/* extsh & extsh. */
1266
GEN_LOGICAL1(extsh, 0x1C, PPC_INTEGER);
B
bellard 已提交
1267
/* nand & nand. */
1268
GEN_LOGICAL2(nand, 0x0E, PPC_INTEGER);
B
bellard 已提交
1269
/* nor & nor. */
1270
GEN_LOGICAL2(nor, 0x03, PPC_INTEGER);
1271

B
bellard 已提交
1272
/* or & or. */
1273 1274
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
{
1275 1276 1277 1278 1279 1280 1281
    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) {
A
aurel32 已提交
1282
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rs]);
1283
        if (rs != rb) {
A
aurel32 已提交
1284
            tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rb]);
1285 1286
            gen_op_or();
        }
A
aurel32 已提交
1287
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
1288 1289 1290
        if (unlikely(Rc(ctx->opcode) != 0))
            gen_set_Rc0(ctx);
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
A
aurel32 已提交
1291
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rs]);
1292
        gen_set_Rc0(ctx);
1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307
#if defined(TARGET_PPC64)
    } else {
        switch (rs) {
        case 1:
            /* Set process priority to low */
            gen_op_store_pri(2);
            break;
        case 6:
            /* Set process priority to medium-low */
            gen_op_store_pri(3);
            break;
        case 2:
            /* Set process priority to normal */
            gen_op_store_pri(4);
            break;
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
#if !defined(CONFIG_USER_ONLY)
        case 31:
            if (ctx->supervisor > 0) {
                /* Set process priority to very low */
                gen_op_store_pri(1);
            }
            break;
        case 5:
            if (ctx->supervisor > 0) {
                /* Set process priority to medium-hight */
                gen_op_store_pri(5);
            }
            break;
        case 3:
            if (ctx->supervisor > 0) {
                /* Set process priority to high */
                gen_op_store_pri(6);
            }
            break;
        case 7:
            if (ctx->supervisor > 1) {
                /* Set process priority to very high */
                gen_op_store_pri(7);
            }
            break;
#endif
1334 1335 1336 1337 1338
        default:
            /* nop */
            break;
        }
#endif
1339 1340 1341
    }
}

B
bellard 已提交
1342
/* orc & orc. */
1343
GEN_LOGICAL2(orc, 0x0C, PPC_INTEGER);
B
bellard 已提交
1344
/* xor & xor. */
1345 1346
GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
{
A
aurel32 已提交
1347
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1348 1349
    /* Optimisation for "set to zero" case */
    if (rS(ctx->opcode) != rB(ctx->opcode)) {
A
aurel32 已提交
1350
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
1351 1352
        gen_op_xor();
    } else {
1353
        tcg_gen_movi_tl(cpu_T[0], 0);
1354
    }
A
aurel32 已提交
1355
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1356 1357
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
1358
}
B
bellard 已提交
1359 1360 1361
/* ori */
GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1362
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1363

1364 1365
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
1366
        /* XXX: should handle special NOPs for POWER series */
1367
        return;
1368
    }
A
aurel32 已提交
1369
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1370
    if (likely(uimm != 0))
B
bellard 已提交
1371
        gen_op_ori(uimm);
A
aurel32 已提交
1372
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
1373 1374 1375 1376
}
/* oris */
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1377
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1378

1379 1380 1381
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1382
    }
A
aurel32 已提交
1383
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1384
    if (likely(uimm != 0))
B
bellard 已提交
1385
        gen_op_ori(uimm << 16);
A
aurel32 已提交
1386
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
1387 1388 1389 1390
}
/* xori */
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1391
    target_ulong uimm = UIMM(ctx->opcode);
1392 1393 1394 1395 1396

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
A
aurel32 已提交
1397
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1398 1399
    if (likely(uimm != 0))
        gen_op_xori(uimm);
A
aurel32 已提交
1400
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
1401 1402 1403 1404 1405
}

/* xoris */
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1406
    target_ulong uimm = UIMM(ctx->opcode);
1407 1408 1409 1410 1411

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
A
aurel32 已提交
1412
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1413 1414
    if (likely(uimm != 0))
        gen_op_xori(uimm << 16);
A
aurel32 已提交
1415
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
1416 1417
}

1418
/* popcntb : PowerPC 2.03 specification */
1419
GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB)
1420
{
A
aurel32 已提交
1421
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1422 1423
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
A
aurel32 已提交
1424
        gen_op_popcntb_64();
1425 1426
    else
#endif
A
aurel32 已提交
1427
        gen_op_popcntb();
A
aurel32 已提交
1428
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1429 1430 1431 1432 1433 1434 1435 1436 1437
}

#if defined(TARGET_PPC64)
/* extsw & extsw. */
GEN_LOGICAL1(extsw, 0x1E, PPC_64B);
/* cntlzd */
GEN_LOGICAL1(cntlzd, 0x01, PPC_64B);
#endif

B
bellard 已提交
1438 1439 1440 1441
/***                             Integer rotate                            ***/
/* rlwimi & rlwimi. */
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1442 1443
    target_ulong mask;
    uint32_t mb, me, sh;
B
bellard 已提交
1444 1445 1446

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1447 1448 1449
    sh = SH(ctx->opcode);
    if (likely(sh == 0)) {
        if (likely(mb == 0 && me == 31)) {
A
aurel32 已提交
1450
            tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1451 1452
            goto do_store;
        } else if (likely(mb == 31 && me == 0)) {
A
aurel32 已提交
1453
            tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1454 1455
            goto do_store;
        }
A
aurel32 已提交
1456 1457
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1458 1459
        goto do_mask;
    }
A
aurel32 已提交
1460 1461
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
    gen_op_rotli32_T0(SH(ctx->opcode));
 do_mask:
#if defined(TARGET_PPC64)
    mb += 32;
    me += 32;
#endif
    mask = MASK(mb, me);
    gen_op_andi_T0(mask);
    gen_op_andi_T1(~mask);
    gen_op_or();
 do_store:
A
aurel32 已提交
1473
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1474 1475
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
B
bellard 已提交
1476 1477 1478 1479 1480
}
/* rlwinm & rlwinm. */
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    uint32_t mb, me, sh;
1481

B
bellard 已提交
1482 1483 1484
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
A
aurel32 已提交
1485
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
    if (likely(sh == 0)) {
        goto do_mask;
    }
    if (likely(mb == 0)) {
        if (likely(me == 31)) {
            gen_op_rotli32_T0(sh);
            goto do_store;
        } else if (likely(me == (31 - sh))) {
            gen_op_sli_T0(sh);
            goto do_store;
B
bellard 已提交
1496
        }
1497 1498 1499 1500
    } else if (likely(me == 31)) {
        if (likely(sh == (32 - mb))) {
            gen_op_srli_T0(mb);
            goto do_store;
B
bellard 已提交
1501 1502
        }
    }
1503 1504 1505 1506 1507 1508 1509 1510
    gen_op_rotli32_T0(sh);
 do_mask:
#if defined(TARGET_PPC64)
    mb += 32;
    me += 32;
#endif
    gen_op_andi_T0(MASK(mb, me));
 do_store:
A
aurel32 已提交
1511
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1512 1513
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
B
bellard 已提交
1514 1515 1516 1517 1518 1519 1520 1521
}
/* rlwnm & rlwnm. */
GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    uint32_t mb, me;

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
A
aurel32 已提交
1522 1523
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
1524 1525 1526 1527 1528 1529 1530
    gen_op_rotl32_T0_T1();
    if (unlikely(mb != 0 || me != 31)) {
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
        gen_op_andi_T0(MASK(mb, me));
B
bellard 已提交
1531
    }
A
aurel32 已提交
1532
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1533 1534
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
B
bellard 已提交
1535 1536
}

1537 1538
#if defined(TARGET_PPC64)
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
1539
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1540 1541 1542
{                                                                             \
    gen_##name(ctx, 0);                                                       \
}                                                                             \
1543 1544
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1545 1546 1547 1548
{                                                                             \
    gen_##name(ctx, 1);                                                       \
}
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
1549
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1550 1551 1552
{                                                                             \
    gen_##name(ctx, 0, 0);                                                    \
}                                                                             \
1553 1554
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1555 1556 1557
{                                                                             \
    gen_##name(ctx, 0, 1);                                                    \
}                                                                             \
1558 1559
GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1560 1561 1562
{                                                                             \
    gen_##name(ctx, 1, 0);                                                    \
}                                                                             \
1563 1564
GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1565 1566 1567
{                                                                             \
    gen_##name(ctx, 1, 1);                                                    \
}
J
j_mayer 已提交
1568

1569
static always_inline void gen_andi_T0_64 (DisasContext *ctx, uint64_t mask)
1570 1571 1572 1573 1574 1575 1576
{
    if (mask >> 32)
        gen_op_andi_T0_64(mask >> 32, mask & 0xFFFFFFFF);
    else
        gen_op_andi_T0(mask);
}

1577
static always_inline void gen_andi_T1_64 (DisasContext *ctx, uint64_t mask)
1578 1579 1580 1581 1582 1583 1584
{
    if (mask >> 32)
        gen_op_andi_T1_64(mask >> 32, mask & 0xFFFFFFFF);
    else
        gen_op_andi_T1(mask);
}

1585 1586
static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
                                      uint32_t me, uint32_t sh)
J
j_mayer 已提交
1587
{
A
aurel32 已提交
1588
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
J
j_mayer 已提交
1589 1590 1591 1592 1593
    if (likely(sh == 0)) {
        goto do_mask;
    }
    if (likely(mb == 0)) {
        if (likely(me == 63)) {
1594
            gen_op_rotli64_T0(sh);
J
j_mayer 已提交
1595 1596 1597 1598 1599 1600 1601
            goto do_store;
        } else if (likely(me == (63 - sh))) {
            gen_op_sli_T0(sh);
            goto do_store;
        }
    } else if (likely(me == 63)) {
        if (likely(sh == (64 - mb))) {
1602
            gen_op_srli_T0_64(mb);
J
j_mayer 已提交
1603 1604 1605 1606 1607
            goto do_store;
        }
    }
    gen_op_rotli64_T0(sh);
 do_mask:
1608
    gen_andi_T0_64(ctx, MASK(mb, me));
J
j_mayer 已提交
1609
 do_store:
A
aurel32 已提交
1610
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
J
j_mayer 已提交
1611 1612 1613
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}
1614
/* rldicl - rldicl. */
1615
static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1616
{
J
j_mayer 已提交
1617
    uint32_t sh, mb;
1618

J
j_mayer 已提交
1619 1620
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1621
    gen_rldinm(ctx, mb, 63, sh);
1622
}
J
j_mayer 已提交
1623
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1624
/* rldicr - rldicr. */
1625
static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1626
{
J
j_mayer 已提交
1627
    uint32_t sh, me;
1628

J
j_mayer 已提交
1629 1630
    sh = SH(ctx->opcode) | (shn << 5);
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1631
    gen_rldinm(ctx, 0, me, sh);
1632
}
J
j_mayer 已提交
1633
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1634
/* rldic - rldic. */
1635
static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1636
{
J
j_mayer 已提交
1637
    uint32_t sh, mb;
1638

J
j_mayer 已提交
1639 1640
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1641 1642 1643 1644
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

1645 1646
static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
                                     uint32_t me)
J
j_mayer 已提交
1647
{
A
aurel32 已提交
1648 1649
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
1650 1651
    gen_op_rotl64_T0_T1();
    if (unlikely(mb != 0 || me != 63)) {
1652
        gen_andi_T0_64(ctx, MASK(mb, me));
J
j_mayer 已提交
1653
    }
A
aurel32 已提交
1654
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
J
j_mayer 已提交
1655 1656
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
1657
}
J
j_mayer 已提交
1658

1659
/* rldcl - rldcl. */
1660
static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1661
{
J
j_mayer 已提交
1662
    uint32_t mb;
1663

J
j_mayer 已提交
1664
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1665
    gen_rldnm(ctx, mb, 63);
1666
}
1667
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1668
/* rldcr - rldcr. */
1669
static always_inline void gen_rldcr (DisasContext *ctx, int men)
1670
{
J
j_mayer 已提交
1671
    uint32_t me;
1672

J
j_mayer 已提交
1673
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1674
    gen_rldnm(ctx, 0, me);
1675
}
1676
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1677
/* rldimi - rldimi. */
1678
static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1679
{
J
j_mayer 已提交
1680
    uint64_t mask;
1681
    uint32_t sh, mb, me;
1682

J
j_mayer 已提交
1683 1684
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
1685
    me = 63 - sh;
J
j_mayer 已提交
1686 1687
    if (likely(sh == 0)) {
        if (likely(mb == 0)) {
A
aurel32 已提交
1688
            tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
J
j_mayer 已提交
1689 1690
            goto do_store;
        }
A
aurel32 已提交
1691 1692
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
J
j_mayer 已提交
1693 1694
        goto do_mask;
    }
A
aurel32 已提交
1695 1696
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1697
    gen_op_rotli64_T0(sh);
J
j_mayer 已提交
1698
 do_mask:
1699
    mask = MASK(mb, me);
1700 1701
    gen_andi_T0_64(ctx, mask);
    gen_andi_T1_64(ctx, ~mask);
J
j_mayer 已提交
1702 1703
    gen_op_or();
 do_store:
A
aurel32 已提交
1704
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
J
j_mayer 已提交
1705 1706
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
1707
}
1708
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1709 1710
#endif

B
bellard 已提交
1711 1712
/***                             Integer shift                             ***/
/* slw & slw. */
1713
__GEN_LOGICAL2(slw, 0x18, 0x00, PPC_INTEGER);
B
bellard 已提交
1714
/* sraw & sraw. */
1715
__GEN_LOGICAL2(sraw, 0x18, 0x18, PPC_INTEGER);
B
bellard 已提交
1716 1717 1718
/* srawi & srawi. */
GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
{
1719
    int mb, me;
A
aurel32 已提交
1720
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1721
    if (SH(ctx->opcode) != 0) {
1722
        tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1723 1724 1725 1726 1727 1728 1729 1730
        mb = 32 - SH(ctx->opcode);
        me = 31;
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
        gen_op_srawi(SH(ctx->opcode), MASK(mb, me));
    }
A
aurel32 已提交
1731
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1732 1733
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
B
bellard 已提交
1734 1735
}
/* srw & srw. */
1736 1737 1738 1739 1740 1741 1742 1743
__GEN_LOGICAL2(srw, 0x18, 0x10, PPC_INTEGER);

#if defined(TARGET_PPC64)
/* sld & sld. */
__GEN_LOGICAL2(sld, 0x1B, 0x00, PPC_64B);
/* srad & srad. */
__GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B);
/* sradi & sradi. */
1744
static always_inline void gen_sradi (DisasContext *ctx, int n)
1745 1746 1747 1748
{
    uint64_t mask;
    int sh, mb, me;

A
aurel32 已提交
1749
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1750 1751
    sh = SH(ctx->opcode) + (n << 5);
    if (sh != 0) {
1752
        tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1753 1754 1755 1756 1757
        mb = 64 - SH(ctx->opcode);
        me = 63;
        mask = MASK(mb, me);
        gen_op_sradi(sh, mask >> 32, mask);
    }
A
aurel32 已提交
1758
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1759 1760 1761
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}
1762
GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
1763 1764 1765
{
    gen_sradi(ctx, 0);
}
1766
GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
1767 1768 1769 1770 1771 1772
{
    gen_sradi(ctx, 1);
}
/* srd & srd. */
__GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
#endif
B
bellard 已提交
1773 1774

/***                       Floating-Point arithmetic                       ***/
1775
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
1776
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
1777
{                                                                             \
1778
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1779
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1780 1781
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
1782 1783 1784
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rC(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[2], cpu_fpr[rB(ctx->opcode)]);                     \
1785
    gen_reset_fpstatus();                                                     \
1786 1787 1788 1789
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
A
aurel32 已提交
1790
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
1791
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
1792 1793
}

1794 1795 1796
#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);
1797

1798 1799
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
1800
{                                                                             \
1801
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1802
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1803 1804
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
1805 1806
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);                     \
1807
    gen_reset_fpstatus();                                                     \
1808 1809 1810 1811
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
A
aurel32 已提交
1812
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
1813
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
1814
}
1815 1816 1817
#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);
1818

1819 1820
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
1821
{                                                                             \
1822
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1823
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1824 1825
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
1826 1827
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rC(ctx->opcode)]);                     \
1828
    gen_reset_fpstatus();                                                     \
1829 1830 1831 1832
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
A
aurel32 已提交
1833
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
1834
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
1835
}
1836 1837 1838
#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);
1839

1840
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
1841
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
1842
{                                                                             \
1843
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1844
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1845 1846
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
1847
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);                     \
1848
    gen_reset_fpstatus();                                                     \
1849
    gen_op_f##name();                                                         \
A
aurel32 已提交
1850
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
1851
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
1852 1853
}

1854
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
1855
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)                        \
1856
{                                                                             \
1857
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1858
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1859 1860
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
1861
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);                     \
1862
    gen_reset_fpstatus();                                                     \
1863
    gen_op_f##name();                                                         \
A
aurel32 已提交
1864
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
1865
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
1866 1867
}

1868
/* fadd - fadds */
1869
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
1870
/* fdiv - fdivs */
1871
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
1872
/* fmul - fmuls */
1873
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
1874

1875
/* fre */
1876
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
1877

1878
/* fres */
1879
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
1880

1881
/* frsqrte */
1882 1883 1884 1885 1886 1887 1888 1889
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
static always_inline void gen_op_frsqrtes (void)
{
    gen_op_frsqrte();
    gen_op_frsp();
}
1890
GEN_FLOAT_BS(rsqrtes, 0x3B, 0x1A, 1, PPC_FLOAT_FRSQRTES);
B
bellard 已提交
1891

1892
/* fsel */
1893
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
1894
/* fsub - fsubs */
1895
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
1896 1897
/* Optional: */
/* fsqrt */
1898
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1899
{
1900
    if (unlikely(!ctx->fpu_enabled)) {
1901
        GEN_EXCP_NO_FP(ctx);
1902 1903
        return;
    }
A
aurel32 已提交
1904
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
1905
    gen_reset_fpstatus();
1906
    gen_op_fsqrt();
A
aurel32 已提交
1907
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
1908
    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1909
}
B
bellard 已提交
1910

1911
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
B
bellard 已提交
1912
{
1913
    if (unlikely(!ctx->fpu_enabled)) {
1914
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1915 1916
        return;
    }
A
aurel32 已提交
1917
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
1918
    gen_reset_fpstatus();
1919 1920
    gen_op_fsqrt();
    gen_op_frsp();
A
aurel32 已提交
1921
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
1922
    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
B
bellard 已提交
1923 1924 1925
}

/***                     Floating-Point multiply-and-add                   ***/
1926
/* fmadd - fmadds */
1927
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
1928
/* fmsub - fmsubs */
1929
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
1930
/* fnmadd - fnmadds */
1931
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
1932
/* fnmsub - fnmsubs */
1933
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
1934 1935 1936

/***                     Floating-Point round & convert                    ***/
/* fctiw */
1937
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
1938
/* fctiwz */
1939
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
1940
/* frsp */
1941
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
1942 1943
#if defined(TARGET_PPC64)
/* fcfid */
1944
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
1945
/* fctid */
1946
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
1947
/* fctidz */
1948
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
1949
#endif
B
bellard 已提交
1950

1951
/* frin */
1952
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
1953
/* friz */
1954
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
1955
/* frip */
1956
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
1957
/* frim */
1958
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
1959

B
bellard 已提交
1960 1961
/***                         Floating-Point compare                        ***/
/* fcmpo */
1962
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
B
bellard 已提交
1963
{
1964
    if (unlikely(!ctx->fpu_enabled)) {
1965
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1966 1967
        return;
    }
A
aurel32 已提交
1968 1969
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
1970
    gen_reset_fpstatus();
1971
    gen_op_fcmpo();
A
aurel32 已提交
1972
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
1973
    gen_op_float_check_status();
B
bellard 已提交
1974 1975 1976
}

/* fcmpu */
1977
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
B
bellard 已提交
1978
{
1979
    if (unlikely(!ctx->fpu_enabled)) {
1980
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1981 1982
        return;
    }
A
aurel32 已提交
1983 1984
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
1985
    gen_reset_fpstatus();
1986
    gen_op_fcmpu();
A
aurel32 已提交
1987
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
1988
    gen_op_float_check_status();
B
bellard 已提交
1989 1990
}

1991 1992
/***                         Floating-point move                           ***/
/* fabs */
1993 1994
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
1995 1996

/* fmr  - fmr. */
1997
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
1998 1999
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
{
2000
    if (unlikely(!ctx->fpu_enabled)) {
2001
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2002 2003
        return;
    }
A
aurel32 已提交
2004 2005
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2006
    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
2007 2008 2009
}

/* fnabs */
2010 2011
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2012
/* fneg */
2013 2014
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2015

B
bellard 已提交
2016 2017 2018 2019
/***                  Floating-Point status & ctrl register                ***/
/* mcrfs */
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
{
2020 2021
    int bfa;

2022
    if (unlikely(!ctx->fpu_enabled)) {
2023
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2024 2025
        return;
    }
2026 2027 2028
    gen_optimize_fprf();
    bfa = 4 * (7 - crfS(ctx->opcode));
    gen_op_load_fpscr_T0(bfa);
A
aurel32 已提交
2029
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
2030
    gen_op_fpscr_resetbit(~(0xF << bfa));
B
bellard 已提交
2031 2032 2033 2034 2035
}

/* mffs */
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
{
2036
    if (unlikely(!ctx->fpu_enabled)) {
2037
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2038 2039
        return;
    }
2040 2041 2042
    gen_optimize_fprf();
    gen_reset_fpstatus();
    gen_op_load_fpscr_FT0();
A
aurel32 已提交
2043
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2044
    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2045 2046 2047 2048 2049
}

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

2052
    if (unlikely(!ctx->fpu_enabled)) {
2053
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2054 2055
        return;
    }
2056 2057 2058 2059 2060 2061 2062 2063 2064
    crb = 32 - (crbD(ctx->opcode) >> 2);
    gen_optimize_fprf();
    gen_reset_fpstatus();
    if (likely(crb != 30 && crb != 29))
        gen_op_fpscr_resetbit(~(1 << crb));
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_op_load_fpcc();
        gen_op_set_Rc0();
    }
B
bellard 已提交
2065 2066 2067 2068 2069
}

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

2072
    if (unlikely(!ctx->fpu_enabled)) {
2073
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2074 2075
        return;
    }
2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087
    crb = 32 - (crbD(ctx->opcode) >> 2);
    gen_optimize_fprf();
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI))
        gen_op_fpscr_setbit(crb);
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_op_load_fpcc();
        gen_op_set_Rc0();
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2088 2089 2090 2091 2092
}

/* mtfsf */
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
{
2093
    if (unlikely(!ctx->fpu_enabled)) {
2094
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2095 2096
        return;
    }
2097
    gen_optimize_fprf();
A
aurel32 已提交
2098
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
2099
    gen_reset_fpstatus();
2100
    gen_op_store_fpscr(FM(ctx->opcode));
2101 2102 2103 2104 2105 2106
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_op_load_fpcc();
        gen_op_set_Rc0();
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2107 2108 2109 2110 2111
}

/* mtfsfi */
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
{
2112 2113
    int bf, sh;

2114
    if (unlikely(!ctx->fpu_enabled)) {
2115
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2116 2117
        return;
    }
2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
    gen_optimize_fprf();
    gen_op_set_FT0(FPIMM(ctx->opcode) << (4 * sh));
    gen_reset_fpstatus();
    gen_op_store_fpscr(1 << sh);
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_op_load_fpcc();
        gen_op_set_Rc0();
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2130 2131
}

2132 2133
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2134 2135
static always_inline void gen_addr_imm_index (DisasContext *ctx,
                                              target_long maskl)
2136 2137 2138
{
    target_long simm = SIMM(ctx->opcode);

2139
    simm &= ~maskl;
2140
    if (rA(ctx->opcode) == 0) {
A
aurel32 已提交
2141
        tcg_gen_movi_tl(cpu_T[0], simm);
2142
    } else {
A
aurel32 已提交
2143
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
2144 2145 2146
        if (likely(simm != 0))
            gen_op_addi(simm);
    }
2147
#ifdef DEBUG_MEMORY_ACCESSES
A
aurel32 已提交
2148
    gen_op_print_mem_EA();
2149
#endif
2150 2151
}

2152
static always_inline void gen_addr_reg_index (DisasContext *ctx)
2153 2154
{
    if (rA(ctx->opcode) == 0) {
A
aurel32 已提交
2155
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
2156
    } else {
A
aurel32 已提交
2157 2158
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
2159 2160
        gen_op_add();
    }
2161
#ifdef DEBUG_MEMORY_ACCESSES
A
aurel32 已提交
2162
    gen_op_print_mem_EA();
2163
#endif
2164 2165
}

2166
static always_inline void gen_addr_register (DisasContext *ctx)
2167 2168
{
    if (rA(ctx->opcode) == 0) {
2169
        tcg_gen_movi_tl(cpu_T[0], 0);
2170
    } else {
A
aurel32 已提交
2171
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
2172
    }
2173
#ifdef DEBUG_MEMORY_ACCESSES
A
aurel32 已提交
2174
    gen_op_print_mem_EA();
2175
#endif
2176 2177
}

2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
#if defined(TARGET_PPC64)
#define _GEN_MEM_FUNCS(name, mode)                                            \
    &gen_op_##name##_##mode,                                                  \
    &gen_op_##name##_le_##mode,                                               \
    &gen_op_##name##_64_##mode,                                               \
    &gen_op_##name##_le_64_##mode
#else
#define _GEN_MEM_FUNCS(name, mode)                                            \
    &gen_op_##name##_##mode,                                                  \
    &gen_op_##name##_le_##mode
#endif
2189
#if defined(CONFIG_USER_ONLY)
2190
#if defined(TARGET_PPC64)
2191
#define NB_MEM_FUNCS 4
2192
#else
2193
#define NB_MEM_FUNCS 2
2194
#endif
2195 2196
#define GEN_MEM_FUNCS(name)                                                   \
    _GEN_MEM_FUNCS(name, raw)
2197
#else
2198
#if defined(TARGET_PPC64)
2199
#define NB_MEM_FUNCS 12
2200
#else
2201
#define NB_MEM_FUNCS 6
2202
#endif
2203 2204 2205 2206 2207 2208 2209 2210
#define GEN_MEM_FUNCS(name)                                                   \
    _GEN_MEM_FUNCS(name, user),                                               \
    _GEN_MEM_FUNCS(name, kernel),                                             \
    _GEN_MEM_FUNCS(name, hypv)
#endif

/***                             Integer load                              ***/
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
2211
/* Byte access routine are endian safe */
2212 2213 2214 2215 2216
#define gen_op_lbz_le_raw       gen_op_lbz_raw
#define gen_op_lbz_le_user      gen_op_lbz_user
#define gen_op_lbz_le_kernel    gen_op_lbz_kernel
#define gen_op_lbz_le_hypv      gen_op_lbz_hypv
#define gen_op_lbz_le_64_raw    gen_op_lbz_64_raw
2217
#define gen_op_lbz_le_64_user   gen_op_lbz_64_user
2218
#define gen_op_lbz_le_64_kernel gen_op_lbz_64_kernel
2219 2220 2221 2222 2223 2224 2225 2226 2227
#define gen_op_lbz_le_64_hypv   gen_op_lbz_64_hypv
#define gen_op_stb_le_raw       gen_op_stb_raw
#define gen_op_stb_le_user      gen_op_stb_user
#define gen_op_stb_le_kernel    gen_op_stb_kernel
#define gen_op_stb_le_hypv      gen_op_stb_hypv
#define gen_op_stb_le_64_raw    gen_op_stb_64_raw
#define gen_op_stb_le_64_user   gen_op_stb_64_user
#define gen_op_stb_le_64_kernel gen_op_stb_64_kernel
#define gen_op_stb_le_64_hypv   gen_op_stb_64_hypv
2228
#define OP_LD_TABLE(width)                                                    \
2229 2230
static GenOpFunc *gen_op_l##width[NB_MEM_FUNCS] = {                           \
    GEN_MEM_FUNCS(l##width),                                                  \
2231 2232
};
#define OP_ST_TABLE(width)                                                    \
2233 2234
static GenOpFunc *gen_op_st##width[NB_MEM_FUNCS] = {                          \
    GEN_MEM_FUNCS(st##width),                                                 \
2235
};
2236

2237 2238
#define GEN_LD(width, opc, type)                                              \
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
B
bellard 已提交
2239
{                                                                             \
J
j_mayer 已提交
2240
    gen_addr_imm_index(ctx, 0);                                               \
2241
    op_ldst(l##width);                                                        \
A
aurel32 已提交
2242
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);                       \
B
bellard 已提交
2243 2244
}

2245 2246
#define GEN_LDU(width, opc, type)                                             \
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
B
bellard 已提交
2247
{                                                                             \
2248 2249
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2250
        GEN_EXCP_INVAL(ctx);                                                  \
2251
        return;                                                               \
2252
    }                                                                         \
J
j_mayer 已提交
2253
    if (type == PPC_64B)                                                      \
2254
        gen_addr_imm_index(ctx, 0x03);                                        \
J
j_mayer 已提交
2255 2256
    else                                                                      \
        gen_addr_imm_index(ctx, 0);                                           \
2257
    op_ldst(l##width);                                                        \
A
aurel32 已提交
2258 2259
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);                       \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
2260 2261
}

2262 2263
#define GEN_LDUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2264
{                                                                             \
2265 2266
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2267
        GEN_EXCP_INVAL(ctx);                                                  \
2268
        return;                                                               \
2269
    }                                                                         \
2270
    gen_addr_reg_index(ctx);                                                  \
2271
    op_ldst(l##width);                                                        \
A
aurel32 已提交
2272 2273
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);                       \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
2274 2275
}

2276 2277
#define GEN_LDX(width, opc2, opc3, type)                                      \
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
B
bellard 已提交
2278
{                                                                             \
2279
    gen_addr_reg_index(ctx);                                                  \
2280
    op_ldst(l##width);                                                        \
A
aurel32 已提交
2281
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);                       \
B
bellard 已提交
2282 2283
}

2284
#define GEN_LDS(width, op, type)                                              \
2285
OP_LD_TABLE(width);                                                           \
2286 2287 2288 2289
GEN_LD(width, op | 0x20, type);                                               \
GEN_LDU(width, op | 0x21, type);                                              \
GEN_LDUX(width, 0x17, op | 0x01, type);                                       \
GEN_LDX(width, 0x17, op | 0x00, type)
B
bellard 已提交
2290 2291

/* lbz lbzu lbzux lbzx */
2292
GEN_LDS(bz, 0x02, PPC_INTEGER);
B
bellard 已提交
2293
/* lha lhau lhaux lhax */
2294
GEN_LDS(ha, 0x0A, PPC_INTEGER);
B
bellard 已提交
2295
/* lhz lhzu lhzux lhzx */
2296
GEN_LDS(hz, 0x08, PPC_INTEGER);
B
bellard 已提交
2297
/* lwz lwzu lwzux lwzx */
2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314
GEN_LDS(wz, 0x00, PPC_INTEGER);
#if defined(TARGET_PPC64)
OP_LD_TABLE(wa);
OP_LD_TABLE(d);
/* lwaux */
GEN_LDUX(wa, 0x15, 0x0B, PPC_64B);
/* lwax */
GEN_LDX(wa, 0x15, 0x0A, PPC_64B);
/* ldux */
GEN_LDUX(d, 0x15, 0x01, PPC_64B);
/* ldx */
GEN_LDX(d, 0x15, 0x00, PPC_64B);
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
{
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
2315
            GEN_EXCP_INVAL(ctx);
2316 2317 2318
            return;
        }
    }
2319
    gen_addr_imm_index(ctx, 0x03);
2320 2321 2322 2323 2324 2325 2326
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
        op_ldst(lwa);
    } else {
        /* ld - ldu */
        op_ldst(ld);
    }
A
aurel32 已提交
2327
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
2328
    if (Rc(ctx->opcode))
A
aurel32 已提交
2329
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
2330
}
2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356
/* lq */
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    int ra, rd;

    /* Restore CPU state */
    if (unlikely(ctx->supervisor == 0)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
        GEN_EXCP_INVAL(ctx);
        return;
    }
    if (unlikely(ctx->mem_idx & 1)) {
        /* Little-endian mode is not handled */
        GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
        return;
    }
    gen_addr_imm_index(ctx, 0x0F);
    op_ldst(ld);
A
aurel32 已提交
2357
    tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[1]);
2358 2359
    gen_op_addi(8);
    op_ldst(ld);
A
aurel32 已提交
2360
    tcg_gen_mov_tl(cpu_gpr[rd + 1], cpu_T[1]);
2361 2362
#endif
}
2363
#endif
B
bellard 已提交
2364 2365

/***                              Integer store                            ***/
2366 2367
#define GEN_ST(width, opc, type)                                              \
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
B
bellard 已提交
2368
{                                                                             \
J
j_mayer 已提交
2369
    gen_addr_imm_index(ctx, 0);                                               \
A
aurel32 已提交
2370
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);                       \
2371
    op_ldst(st##width);                                                       \
B
bellard 已提交
2372 2373
}

2374 2375
#define GEN_STU(width, opc, type)                                             \
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
B
bellard 已提交
2376
{                                                                             \
2377
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2378
        GEN_EXCP_INVAL(ctx);                                                  \
2379
        return;                                                               \
2380
    }                                                                         \
J
j_mayer 已提交
2381
    if (type == PPC_64B)                                                      \
2382
        gen_addr_imm_index(ctx, 0x03);                                        \
J
j_mayer 已提交
2383 2384
    else                                                                      \
        gen_addr_imm_index(ctx, 0);                                           \
A
aurel32 已提交
2385
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);                       \
2386
    op_ldst(st##width);                                                       \
A
aurel32 已提交
2387
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
2388 2389
}

2390 2391
#define GEN_STUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                \
B
bellard 已提交
2392
{                                                                             \
2393
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2394
        GEN_EXCP_INVAL(ctx);                                                  \
2395
        return;                                                               \
2396
    }                                                                         \
2397
    gen_addr_reg_index(ctx);                                                  \
A
aurel32 已提交
2398
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);                       \
2399
    op_ldst(st##width);                                                       \
A
aurel32 已提交
2400
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
2401 2402
}

2403 2404
#define GEN_STX(width, opc2, opc3, type)                                      \
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2405
{                                                                             \
2406
    gen_addr_reg_index(ctx);                                                  \
A
aurel32 已提交
2407
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);                       \
2408
    op_ldst(st##width);                                                       \
B
bellard 已提交
2409 2410
}

2411
#define GEN_STS(width, op, type)                                              \
2412
OP_ST_TABLE(width);                                                           \
2413 2414 2415 2416
GEN_ST(width, op | 0x20, type);                                               \
GEN_STU(width, op | 0x21, type);                                              \
GEN_STUX(width, 0x17, op | 0x01, type);                                       \
GEN_STX(width, 0x17, op | 0x00, type)
B
bellard 已提交
2417 2418

/* stb stbu stbux stbx */
2419
GEN_STS(b, 0x06, PPC_INTEGER);
B
bellard 已提交
2420
/* sth sthu sthux sthx */
2421
GEN_STS(h, 0x0C, PPC_INTEGER);
B
bellard 已提交
2422
/* stw stwu stwux stwx */
2423 2424 2425
GEN_STS(w, 0x04, PPC_INTEGER);
#if defined(TARGET_PPC64)
OP_ST_TABLE(d);
J
j_mayer 已提交
2426 2427
GEN_STUX(d, 0x15, 0x05, PPC_64B);
GEN_STX(d, 0x15, 0x04, PPC_64B);
2428
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2429
{
2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442
    int rs;

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
        GEN_EXCP_PRIVOPC(ctx);
#else
        /* stq */
        if (unlikely(ctx->supervisor == 0)) {
            GEN_EXCP_PRIVOPC(ctx);
            return;
        }
        if (unlikely(rs & 1)) {
2443
            GEN_EXCP_INVAL(ctx);
2444 2445
            return;
        }
2446 2447 2448 2449 2450 2451
        if (unlikely(ctx->mem_idx & 1)) {
            /* Little-endian mode is not handled */
            GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
            return;
        }
        gen_addr_imm_index(ctx, 0x03);
A
aurel32 已提交
2452
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rs]);
2453 2454
        op_ldst(std);
        gen_op_addi(8);
A
aurel32 已提交
2455
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rs + 1]);
2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466
        op_ldst(std);
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
                GEN_EXCP_INVAL(ctx);
                return;
            }
        }
        gen_addr_imm_index(ctx, 0x03);
A
aurel32 已提交
2467
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rs]);
2468 2469
        op_ldst(std);
        if (Rc(ctx->opcode))
A
aurel32 已提交
2470
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
2471 2472 2473
    }
}
#endif
B
bellard 已提交
2474 2475
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
2476
OP_LD_TABLE(hbr);
2477
GEN_LDX(hbr, 0x16, 0x18, PPC_INTEGER);
B
bellard 已提交
2478
/* lwbrx */
2479
OP_LD_TABLE(wbr);
2480
GEN_LDX(wbr, 0x16, 0x10, PPC_INTEGER);
B
bellard 已提交
2481
/* sthbrx */
2482
OP_ST_TABLE(hbr);
2483
GEN_STX(hbr, 0x16, 0x1C, PPC_INTEGER);
B
bellard 已提交
2484
/* stwbrx */
2485
OP_ST_TABLE(wbr);
2486
GEN_STX(wbr, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2487 2488

/***                    Integer load and store multiple                    ***/
2489
#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
2490 2491
static GenOpFunc1 *gen_op_lmw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lmw),
2492
};
2493 2494
static GenOpFunc1 *gen_op_stmw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stmw),
2495
};
2496

B
bellard 已提交
2497 2498 2499
/* lmw */
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
2500
    /* NIP cannot be restored if the memory exception comes from an helper */
2501
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
2502
    gen_addr_imm_index(ctx, 0);
2503
    op_ldstm(lmw, rD(ctx->opcode));
B
bellard 已提交
2504 2505 2506 2507 2508
}

/* stmw */
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
2509
    /* NIP cannot be restored if the memory exception comes from an helper */
2510
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
2511
    gen_addr_imm_index(ctx, 0);
2512
    op_ldstm(stmw, rS(ctx->opcode));
B
bellard 已提交
2513 2514 2515
}

/***                    Integer load and store strings                     ***/
2516 2517
#define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
#define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
2518 2519 2520 2521 2522 2523 2524 2525 2526
/* string load & stores are by definition endian-safe */
#define gen_op_lswi_le_raw       gen_op_lswi_raw
#define gen_op_lswi_le_user      gen_op_lswi_user
#define gen_op_lswi_le_kernel    gen_op_lswi_kernel
#define gen_op_lswi_le_hypv      gen_op_lswi_hypv
#define gen_op_lswi_le_64_raw    gen_op_lswi_raw
#define gen_op_lswi_le_64_user   gen_op_lswi_user
#define gen_op_lswi_le_64_kernel gen_op_lswi_kernel
#define gen_op_lswi_le_64_hypv   gen_op_lswi_hypv
2527 2528
static GenOpFunc1 *gen_op_lswi[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lswi),
2529
};
2530 2531 2532 2533 2534 2535 2536 2537
#define gen_op_lswx_le_raw       gen_op_lswx_raw
#define gen_op_lswx_le_user      gen_op_lswx_user
#define gen_op_lswx_le_kernel    gen_op_lswx_kernel
#define gen_op_lswx_le_hypv      gen_op_lswx_hypv
#define gen_op_lswx_le_64_raw    gen_op_lswx_raw
#define gen_op_lswx_le_64_user   gen_op_lswx_user
#define gen_op_lswx_le_64_kernel gen_op_lswx_kernel
#define gen_op_lswx_le_64_hypv   gen_op_lswx_hypv
2538 2539
static GenOpFunc3 *gen_op_lswx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lswx),
2540
};
2541 2542 2543 2544 2545 2546 2547 2548
#define gen_op_stsw_le_raw       gen_op_stsw_raw
#define gen_op_stsw_le_user      gen_op_stsw_user
#define gen_op_stsw_le_kernel    gen_op_stsw_kernel
#define gen_op_stsw_le_hypv      gen_op_stsw_hypv
#define gen_op_stsw_le_64_raw    gen_op_stsw_raw
#define gen_op_stsw_le_64_user   gen_op_stsw_user
#define gen_op_stsw_le_64_kernel gen_op_stsw_kernel
#define gen_op_stsw_le_64_hypv   gen_op_stsw_hypv
2549 2550
static GenOpFunc1 *gen_op_stsw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stsw),
2551 2552
};

B
bellard 已提交
2553
/* lswi */
2554
/* PowerPC32 specification says we must generate an exception if
2555 2556 2557 2558
 * 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...
 */
2559
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
B
bellard 已提交
2560 2561 2562
{
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
2563
    int ra = rA(ctx->opcode);
B
bellard 已提交
2564 2565 2566 2567 2568
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
2569 2570 2571
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
2572 2573
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
2574
        return;
B
bellard 已提交
2575
    }
2576
    /* NIP cannot be restored if the memory exception comes from an helper */
2577
    gen_update_nip(ctx, ctx->nip - 4);
2578
    gen_addr_register(ctx);
2579
    tcg_gen_movi_tl(cpu_T[1], nb);
2580
    op_ldsts(lswi, start);
B
bellard 已提交
2581 2582 2583
}

/* lswx */
2584
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
B
bellard 已提交
2585
{
2586 2587 2588
    int ra = rA(ctx->opcode);
    int rb = rB(ctx->opcode);

2589
    /* NIP cannot be restored if the memory exception comes from an helper */
2590
    gen_update_nip(ctx, ctx->nip - 4);
2591
    gen_addr_reg_index(ctx);
2592 2593
    if (ra == 0) {
        ra = rb;
B
bellard 已提交
2594
    }
2595 2596
    gen_op_load_xer_bc();
    op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
B
bellard 已提交
2597 2598 2599
}

/* stswi */
2600
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
B
bellard 已提交
2601
{
B
bellard 已提交
2602 2603
    int nb = NB(ctx->opcode);

2604
    /* NIP cannot be restored if the memory exception comes from an helper */
2605
    gen_update_nip(ctx, ctx->nip - 4);
2606
    gen_addr_register(ctx);
B
bellard 已提交
2607 2608
    if (nb == 0)
        nb = 32;
2609
    tcg_gen_movi_tl(cpu_T[1], nb);
2610
    op_ldsts(stsw, rS(ctx->opcode));
B
bellard 已提交
2611 2612 2613
}

/* stswx */
2614
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
B
bellard 已提交
2615
{
2616
    /* NIP cannot be restored if the memory exception comes from an helper */
2617
    gen_update_nip(ctx, ctx->nip - 4);
2618 2619
    gen_addr_reg_index(ctx);
    gen_op_load_xer_bc();
2620
    op_ldsts(stsw, rS(ctx->opcode));
B
bellard 已提交
2621 2622 2623 2624
}

/***                        Memory synchronisation                         ***/
/* eieio */
2625
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
B
bellard 已提交
2626 2627 2628 2629
{
}

/* isync */
2630
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
B
bellard 已提交
2631
{
2632
    GEN_STOP(ctx);
B
bellard 已提交
2633 2634
}

2635 2636
#define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
2637 2638
static GenOpFunc *gen_op_lwarx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lwarx),
2639
};
2640 2641
static GenOpFunc *gen_op_stwcx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stwcx),
B
bellard 已提交
2642
};
2643

2644
/* lwarx */
2645
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
B
bellard 已提交
2646
{
2647 2648
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2649
    gen_addr_reg_index(ctx);
B
bellard 已提交
2650
    op_lwarx();
A
aurel32 已提交
2651
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
B
bellard 已提交
2652 2653 2654
}

/* stwcx. */
2655
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
B
bellard 已提交
2656
{
2657 2658
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2659
    gen_addr_reg_index(ctx);
A
aurel32 已提交
2660
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
2661
    op_stwcx();
B
bellard 已提交
2662 2663
}

J
j_mayer 已提交
2664 2665 2666
#if defined(TARGET_PPC64)
#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
2667 2668
static GenOpFunc *gen_op_ldarx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(ldarx),
J
j_mayer 已提交
2669
};
2670 2671
static GenOpFunc *gen_op_stdcx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stdcx),
J
j_mayer 已提交
2672 2673 2674
};

/* ldarx */
2675
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
J
j_mayer 已提交
2676
{
2677 2678
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
2679 2680
    gen_addr_reg_index(ctx);
    op_ldarx();
A
aurel32 已提交
2681
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
J
j_mayer 已提交
2682 2683 2684
}

/* stdcx. */
2685
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
J
j_mayer 已提交
2686
{
2687 2688
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
2689
    gen_addr_reg_index(ctx);
A
aurel32 已提交
2690
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
J
j_mayer 已提交
2691 2692 2693 2694
    op_stdcx();
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
2695
/* sync */
2696
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
B
bellard 已提交
2697 2698 2699
{
}

2700 2701 2702 2703
/* wait */
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
{
    /* Stop translation, as the CPU is supposed to sleep from now */
2704 2705
    gen_op_wait();
    GEN_EXCP(ctx, EXCP_HLT, 1);
2706 2707
}

B
bellard 已提交
2708
/***                         Floating-point load                           ***/
2709 2710
#define GEN_LDF(width, opc, type)                                             \
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
B
bellard 已提交
2711
{                                                                             \
2712
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2713
        GEN_EXCP_NO_FP(ctx);                                                  \
2714 2715
        return;                                                               \
    }                                                                         \
J
j_mayer 已提交
2716
    gen_addr_imm_index(ctx, 0);                                               \
2717
    op_ldst(l##width);                                                        \
A
aurel32 已提交
2718
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
B
bellard 已提交
2719 2720
}

2721 2722
#define GEN_LDUF(width, opc, type)                                            \
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
B
bellard 已提交
2723
{                                                                             \
2724
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2725
        GEN_EXCP_NO_FP(ctx);                                                  \
2726 2727
        return;                                                               \
    }                                                                         \
2728
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2729
        GEN_EXCP_INVAL(ctx);                                                  \
2730
        return;                                                               \
2731
    }                                                                         \
J
j_mayer 已提交
2732
    gen_addr_imm_index(ctx, 0);                                               \
2733
    op_ldst(l##width);                                                        \
A
aurel32 已提交
2734
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
A
aurel32 已提交
2735
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
2736 2737
}

2738 2739
#define GEN_LDUXF(width, opc, type)                                           \
GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                  \
B
bellard 已提交
2740
{                                                                             \
2741
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2742
        GEN_EXCP_NO_FP(ctx);                                                  \
2743 2744
        return;                                                               \
    }                                                                         \
2745
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2746
        GEN_EXCP_INVAL(ctx);                                                  \
2747
        return;                                                               \
2748
    }                                                                         \
2749
    gen_addr_reg_index(ctx);                                                  \
2750
    op_ldst(l##width);                                                        \
A
aurel32 已提交
2751
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
A
aurel32 已提交
2752
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
2753 2754
}

2755 2756
#define GEN_LDXF(width, opc2, opc3, type)                                     \
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
B
bellard 已提交
2757
{                                                                             \
2758
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2759
        GEN_EXCP_NO_FP(ctx);                                                  \
2760 2761
        return;                                                               \
    }                                                                         \
2762
    gen_addr_reg_index(ctx);                                                  \
2763
    op_ldst(l##width);                                                        \
A
aurel32 已提交
2764
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
B
bellard 已提交
2765 2766
}

2767
#define GEN_LDFS(width, op, type)                                             \
2768
OP_LD_TABLE(width);                                                           \
2769 2770 2771 2772
GEN_LDF(width, op | 0x20, type);                                              \
GEN_LDUF(width, op | 0x21, type);                                             \
GEN_LDUXF(width, op | 0x01, type);                                            \
GEN_LDXF(width, 0x17, op | 0x00, type)
B
bellard 已提交
2773 2774

/* lfd lfdu lfdux lfdx */
2775
GEN_LDFS(fd, 0x12, PPC_FLOAT);
B
bellard 已提交
2776
/* lfs lfsu lfsux lfsx */
2777
GEN_LDFS(fs, 0x10, PPC_FLOAT);
B
bellard 已提交
2778 2779

/***                         Floating-point store                          ***/
2780 2781
#define GEN_STF(width, opc, type)                                             \
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
B
bellard 已提交
2782
{                                                                             \
2783
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2784
        GEN_EXCP_NO_FP(ctx);                                                  \
2785 2786
        return;                                                               \
    }                                                                         \
J
j_mayer 已提交
2787
    gen_addr_imm_index(ctx, 0);                                               \
A
aurel32 已提交
2788
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
2789
    op_ldst(st##width);                                                       \
B
bellard 已提交
2790 2791
}

2792 2793
#define GEN_STUF(width, opc, type)                                            \
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
B
bellard 已提交
2794
{                                                                             \
2795
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2796
        GEN_EXCP_NO_FP(ctx);                                                  \
2797 2798
        return;                                                               \
    }                                                                         \
2799
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2800
        GEN_EXCP_INVAL(ctx);                                                  \
2801
        return;                                                               \
2802
    }                                                                         \
J
j_mayer 已提交
2803
    gen_addr_imm_index(ctx, 0);                                               \
A
aurel32 已提交
2804
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
2805
    op_ldst(st##width);                                                       \
A
aurel32 已提交
2806
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
2807 2808
}

2809 2810
#define GEN_STUXF(width, opc, type)                                           \
GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                 \
B
bellard 已提交
2811
{                                                                             \
2812
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2813
        GEN_EXCP_NO_FP(ctx);                                                  \
2814 2815
        return;                                                               \
    }                                                                         \
2816
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2817
        GEN_EXCP_INVAL(ctx);                                                  \
2818
        return;                                                               \
2819
    }                                                                         \
2820
    gen_addr_reg_index(ctx);                                                  \
A
aurel32 已提交
2821
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
2822
    op_ldst(st##width);                                                       \
A
aurel32 已提交
2823
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
2824 2825
}

2826 2827
#define GEN_STXF(width, opc2, opc3, type)                                     \
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2828
{                                                                             \
2829
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2830
        GEN_EXCP_NO_FP(ctx);                                                  \
2831 2832
        return;                                                               \
    }                                                                         \
2833
    gen_addr_reg_index(ctx);                                                  \
A
aurel32 已提交
2834
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
2835
    op_ldst(st##width);                                                       \
B
bellard 已提交
2836 2837
}

2838
#define GEN_STFS(width, op, type)                                             \
2839
OP_ST_TABLE(width);                                                           \
2840 2841 2842 2843
GEN_STF(width, op | 0x20, type);                                              \
GEN_STUF(width, op | 0x21, type);                                             \
GEN_STUXF(width, op | 0x01, type);                                            \
GEN_STXF(width, 0x17, op | 0x00, type)
B
bellard 已提交
2844 2845

/* stfd stfdu stfdux stfdx */
2846
GEN_STFS(fd, 0x16, PPC_FLOAT);
B
bellard 已提交
2847
/* stfs stfsu stfsux stfsx */
2848
GEN_STFS(fs, 0x14, PPC_FLOAT);
B
bellard 已提交
2849 2850 2851

/* Optional: */
/* stfiwx */
J
j_mayer 已提交
2852 2853
OP_ST_TABLE(fiw);
GEN_STXF(fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
2854 2855

/***                                Branch                                 ***/
2856 2857
static always_inline void gen_goto_tb (DisasContext *ctx, int n,
                                       target_ulong dest)
2858 2859 2860
{
    TranslationBlock *tb;
    tb = ctx->tb;
B
bellard 已提交
2861
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2862
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
2863
        tcg_gen_goto_tb(n);
A
aurel32 已提交
2864
        tcg_gen_movi_tl(cpu_T[1], dest);
2865 2866 2867 2868 2869 2870
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_b_T1_64();
        else
#endif
            gen_op_b_T1();
B
bellard 已提交
2871
        tcg_gen_exit_tb((long)tb + n);
2872
    } else {
A
aurel32 已提交
2873
        tcg_gen_movi_tl(cpu_T[1], dest);
2874 2875 2876 2877 2878 2879
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_b_T1_64();
        else
#endif
            gen_op_b_T1();
2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
                 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
                ctx->exception == POWERPC_EXCP_BRANCH) {
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
                GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0);
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
                gen_update_nip(ctx, dest);
                gen_op_debug();
            }
        }
B
bellard 已提交
2894
        tcg_gen_exit_tb(0);
2895
    }
B
bellard 已提交
2896 2897
}

2898
static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
2899 2900 2901 2902 2903 2904 2905 2906 2907
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode != 0 && (nip >> 32))
        gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
    else
#endif
        gen_op_setlr(ctx->nip);
}

B
bellard 已提交
2908 2909 2910
/* b ba bl bla */
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
2911
    target_ulong li, target;
B
bellard 已提交
2912

2913
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
2914
    /* sign extend LI */
2915
#if defined(TARGET_PPC64)
2916 2917 2918
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
2919
#endif
2920
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
2921
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
2922
        target = ctx->nip + li - 4;
B
bellard 已提交
2923
    else
2924
        target = li;
2925
#if defined(TARGET_PPC64)
2926 2927
    if (!ctx->sf_mode)
        target = (uint32_t)target;
2928
#endif
2929 2930
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
2931
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
2932 2933
}

2934 2935 2936 2937
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

2938
static always_inline void gen_bcond (DisasContext *ctx, int type)
2939
{
2940 2941
    target_ulong target = 0;
    target_ulong li;
2942 2943 2944
    uint32_t bo = BO(ctx->opcode);
    uint32_t bi = BI(ctx->opcode);
    uint32_t mask;
2945

2946
    ctx->exception = POWERPC_EXCP_BRANCH;
2947
    if ((bo & 0x4) == 0)
2948
        gen_op_dec_ctr();
2949 2950
    switch(type) {
    case BCOND_IM:
2951 2952
        li = (target_long)((int16_t)(BD(ctx->opcode)));
        if (likely(AA(ctx->opcode) == 0)) {
B
bellard 已提交
2953
            target = ctx->nip + li - 4;
2954 2955 2956
        } else {
            target = li;
        }
2957 2958 2959 2960
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode)
            target = (uint32_t)target;
#endif
2961 2962 2963 2964 2965 2966 2967 2968 2969
        break;
    case BCOND_CTR:
        gen_op_movl_T1_ctr();
        break;
    default:
    case BCOND_LR:
        gen_op_movl_T1_lr();
        break;
    }
2970 2971
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
2972
    if (bo & 0x10) {
2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989
        /* No CR condition */
        switch (bo & 0x6) {
        case 0:
#if defined(TARGET_PPC64)
            if (ctx->sf_mode)
                gen_op_test_ctr_64();
            else
#endif
                gen_op_test_ctr();
            break;
        case 2:
#if defined(TARGET_PPC64)
            if (ctx->sf_mode)
                gen_op_test_ctrz_64();
            else
#endif
                gen_op_test_ctrz();
2990 2991
            break;
        default:
2992 2993
        case 4:
        case 6:
2994
            if (type == BCOND_IM) {
2995
                gen_goto_tb(ctx, 0, target);
2996
                return;
2997
            } else {
2998 2999 3000 3001 3002 3003
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_b_T1_64();
                else
#endif
                    gen_op_b_T1();
3004
                goto no_test;
3005
            }
3006
            break;
3007
        }
3008 3009
    } else {
        mask = 1 << (3 - (bi & 0x03));
A
aurel32 已提交
3010
        tcg_gen_mov_i32(cpu_T[0], cpu_crf[bi >> 2]);
3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031
        if (bo & 0x8) {
            switch (bo & 0x6) {
            case 0:
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_test_ctr_true_64(mask);
                else
#endif
                    gen_op_test_ctr_true(mask);
                break;
            case 2:
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_test_ctrz_true_64(mask);
                else
#endif
                    gen_op_test_ctrz_true(mask);
                break;
            default:
            case 4:
            case 6:
3032
                gen_op_test_true(mask);
3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043
                break;
            }
        } else {
            switch (bo & 0x6) {
            case 0:
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_test_ctr_false_64(mask);
                else
#endif
                    gen_op_test_ctr_false(mask);
3044
                break;
3045 3046 3047 3048 3049 3050 3051 3052
            case 2:
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_test_ctrz_false_64(mask);
                else
#endif
                    gen_op_test_ctrz_false(mask);
                break;
3053
            default:
3054 3055
            case 4:
            case 6:
3056
                gen_op_test_false(mask);
3057 3058 3059 3060
                break;
            }
        }
    }
3061
    if (type == BCOND_IM) {
B
bellard 已提交
3062 3063
        int l1 = gen_new_label();
        gen_op_jz_T0(l1);
3064
        gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3065
        gen_set_label(l1);
3066
        gen_goto_tb(ctx, 1, ctx->nip);
3067
    } else {
3068 3069 3070 3071 3072 3073
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_btest_T1_64(ctx->nip >> 32, ctx->nip);
        else
#endif
            gen_op_btest_T1(ctx->nip);
3074
    no_test:
3075 3076
        if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
            gen_update_nip(ctx, ctx->nip);
J
j_mayer 已提交
3077
            gen_op_debug();
3078
        }
B
bellard 已提交
3079
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3080
    }
3081 3082 3083
}

GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3084
{
3085 3086 3087 3088
    gen_bcond(ctx, BCOND_IM);
}

GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3089
{
3090 3091 3092 3093
    gen_bcond(ctx, BCOND_CTR);
}

GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3094
{
3095 3096
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3097 3098 3099 3100 3101

/***                      Condition register logical                       ***/
#define GEN_CRLOGIC(op, opc)                                                  \
GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)                 \
{                                                                             \
3102 3103
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
A
aurel32 已提交
3104
    tcg_gen_mov_i32(cpu_T[0], cpu_crf[crbA(ctx->opcode) >> 2]);               \
3105 3106 3107 3108 3109
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
        gen_op_srli_T0(sh);                                                   \
    else if (sh < 0)                                                          \
        gen_op_sli_T0(-sh);                                                   \
A
aurel32 已提交
3110
    tcg_gen_mov_i32(cpu_T[1], cpu_crf[crbB(ctx->opcode) >> 2]);               \
3111 3112 3113 3114 3115
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
        gen_op_srli_T1(sh);                                                   \
    else if (sh < 0)                                                          \
        gen_op_sli_T1(-sh);                                                   \
B
bellard 已提交
3116
    gen_op_##op();                                                            \
3117 3118
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
    gen_op_andi_T0(bitmask);                                                  \
A
aurel32 已提交
3119
    tcg_gen_andi_i32(cpu_T[1], cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask);    \
3120
    gen_op_or();                                                              \
A
aurel32 已提交
3121
    tcg_gen_andi_i32(cpu_crf[crbD(ctx->opcode) >> 2], cpu_T[0], 0xf);         \
B
bellard 已提交
3122 3123 3124
}

/* crand */
3125
GEN_CRLOGIC(and, 0x08);
B
bellard 已提交
3126
/* crandc */
3127
GEN_CRLOGIC(andc, 0x04);
B
bellard 已提交
3128
/* creqv */
3129
GEN_CRLOGIC(eqv, 0x09);
B
bellard 已提交
3130
/* crnand */
3131
GEN_CRLOGIC(nand, 0x07);
B
bellard 已提交
3132
/* crnor */
3133
GEN_CRLOGIC(nor, 0x01);
B
bellard 已提交
3134
/* cror */
3135
GEN_CRLOGIC(or, 0x0E);
B
bellard 已提交
3136
/* crorc */
3137
GEN_CRLOGIC(orc, 0x0D);
B
bellard 已提交
3138
/* crxor */
3139
GEN_CRLOGIC(xor, 0x06);
B
bellard 已提交
3140 3141 3142
/* mcrf */
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
{
A
aurel32 已提交
3143
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3144 3145 3146 3147
}

/***                           System linkage                              ***/
/* rfi (supervisor only) */
3148
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
B
bellard 已提交
3149
{
3150
#if defined(CONFIG_USER_ONLY)
3151
    GEN_EXCP_PRIVOPC(ctx);
3152 3153
#else
    /* Restore CPU state */
3154
    if (unlikely(!ctx->supervisor)) {
3155
        GEN_EXCP_PRIVOPC(ctx);
3156
        return;
3157
    }
3158
    gen_op_rfi();
3159
    GEN_SYNC(ctx);
3160
#endif
B
bellard 已提交
3161 3162
}

J
j_mayer 已提交
3163
#if defined(TARGET_PPC64)
3164
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
J
j_mayer 已提交
3165 3166
{
#if defined(CONFIG_USER_ONLY)
3167
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3168 3169 3170
#else
    /* Restore CPU state */
    if (unlikely(!ctx->supervisor)) {
3171
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3172 3173
        return;
    }
3174
    gen_op_rfid();
3175
    GEN_SYNC(ctx);
J
j_mayer 已提交
3176 3177 3178
#endif
}

J
j_mayer 已提交
3179
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    /* Restore CPU state */
    if (unlikely(ctx->supervisor <= 1)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
    gen_op_hrfid();
    GEN_SYNC(ctx);
#endif
}
#endif

B
bellard 已提交
3195
/* sc */
3196 3197 3198 3199 3200
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
3201
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
B
bellard 已提交
3202
{
3203 3204 3205
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
3206
    GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3207 3208 3209 3210
}

/***                                Trap                                   ***/
/* tw */
3211
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
B
bellard 已提交
3212
{
A
aurel32 已提交
3213 3214
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3215
    /* Update the nip since this might generate a trap exception */
3216
    gen_update_nip(ctx, ctx->nip);
3217
    gen_op_tw(TO(ctx->opcode));
B
bellard 已提交
3218 3219 3220 3221 3222
}

/* twi */
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
A
aurel32 已提交
3223
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
3224
    tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3225 3226
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3227
    gen_op_tw(TO(ctx->opcode));
B
bellard 已提交
3228 3229
}

3230 3231 3232 3233
#if defined(TARGET_PPC64)
/* td */
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
{
A
aurel32 已提交
3234 3235
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3236 3237 3238 3239 3240 3241 3242 3243
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
    gen_op_td(TO(ctx->opcode));
}

/* tdi */
GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
{
A
aurel32 已提交
3244
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
3245
    tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3246 3247 3248 3249 3250 3251
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
    gen_op_td(TO(ctx->opcode));
}
#endif

B
bellard 已提交
3252 3253 3254 3255 3256
/***                          Processor control                            ***/
/* mcrxr */
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
{
    gen_op_load_xer_cr();
A
aurel32 已提交
3257
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
J
j_mayer 已提交
3258 3259
    gen_op_clear_xer_ov();
    gen_op_clear_xer_ca();
B
bellard 已提交
3260 3261 3262
}

/* mfcr */
3263
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
B
bellard 已提交
3264
{
3265
    uint32_t crm, crn;
3266

3267 3268 3269 3270
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
        if (likely((crm ^ (crm - 1)) == 0)) {
            crn = ffs(crm);
A
aurel32 已提交
3271
            tcg_gen_mov_i32(cpu_T[0], cpu_crf[7 - crn]);
3272
        }
3273
    } else {
A
aurel32 已提交
3274
        gen_op_load_cr();
3275
    }
A
aurel32 已提交
3276
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
B
bellard 已提交
3277 3278 3279 3280 3281
}

/* mfmsr */
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
{
3282
#if defined(CONFIG_USER_ONLY)
3283
    GEN_EXCP_PRIVREG(ctx);
3284
#else
3285
    if (unlikely(!ctx->supervisor)) {
3286
        GEN_EXCP_PRIVREG(ctx);
3287
        return;
3288
    }
A
aurel32 已提交
3289
    gen_op_load_msr();
A
aurel32 已提交
3290
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3291
#endif
B
bellard 已提交
3292 3293
}

J
j_mayer 已提交
3294
#if 1
3295
#define SPR_NOACCESS ((void *)(-1UL))
3296 3297 3298 3299 3300 3301 3302 3303 3304
#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 已提交
3305
/* mfspr */
3306
static always_inline void gen_op_mfspr (DisasContext *ctx)
B
bellard 已提交
3307
{
3308
    void (*read_cb)(void *opaque, int sprn);
B
bellard 已提交
3309 3310
    uint32_t sprn = SPR(ctx->opcode);

3311
#if !defined(CONFIG_USER_ONLY)
3312 3313
    if (ctx->supervisor == 2)
        read_cb = ctx->spr_cb[sprn].hea_read;
3314
    else if (ctx->supervisor)
3315 3316
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3317
#endif
3318
        read_cb = ctx->spr_cb[sprn].uea_read;
3319 3320
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
3321
            (*read_cb)(ctx, sprn);
A
aurel32 已提交
3322
            tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3323 3324
        } else {
            /* Privilege exception */
3325 3326 3327 3328 3329 3330
            /* 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) {
                if (loglevel != 0) {
3331
                    fprintf(logfile, "Trying to read privileged spr %d %03x at "
J
j_mayer 已提交
3332
                            ADDRX "\n", sprn, sprn, ctx->nip);
3333
                }
J
j_mayer 已提交
3334 3335
                printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
                       sprn, sprn, ctx->nip);
3336
            }
3337
            GEN_EXCP_PRIVREG(ctx);
B
bellard 已提交
3338
        }
3339 3340
    } else {
        /* Not defined */
J
j_mayer 已提交
3341
        if (loglevel != 0) {
J
j_mayer 已提交
3342 3343
            fprintf(logfile, "Trying to read invalid spr %d %03x at "
                    ADDRX "\n", sprn, sprn, ctx->nip);
3344
        }
J
j_mayer 已提交
3345 3346
        printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
               sprn, sprn, ctx->nip);
3347 3348
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3349 3350 3351
    }
}

3352
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
B
bellard 已提交
3353
{
3354
    gen_op_mfspr(ctx);
3355
}
3356 3357

/* mftb */
3358
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3359 3360
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3361 3362 3363
}

/* mtcrf */
3364
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
B
bellard 已提交
3365
{
3366
    uint32_t crm, crn;
3367

A
aurel32 已提交
3368
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3369 3370 3371 3372
    crm = CRM(ctx->opcode);
    if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
        crn = ffs(crm);
        gen_op_srli_T0(crn * 4);
A
aurel32 已提交
3373
        tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_T[0], 0xf);
3374
    } else {
A
aurel32 已提交
3375
        gen_op_store_cr(crm);
3376
    }
B
bellard 已提交
3377 3378 3379
}

/* mtmsr */
J
j_mayer 已提交
3380
#if defined(TARGET_PPC64)
3381
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
J
j_mayer 已提交
3382 3383
{
#if defined(CONFIG_USER_ONLY)
3384
    GEN_EXCP_PRIVREG(ctx);
J
j_mayer 已提交
3385 3386
#else
    if (unlikely(!ctx->supervisor)) {
3387
        GEN_EXCP_PRIVREG(ctx);
J
j_mayer 已提交
3388 3389
        return;
    }
A
aurel32 已提交
3390
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3391 3392 3393 3394
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
        gen_op_update_riee();
    } else {
3395 3396 3397 3398
        /* 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
         */
3399
        gen_update_nip(ctx, ctx->nip);
A
aurel32 已提交
3400
        gen_op_store_msr();
3401 3402
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
3403
        ctx->exception = POWERPC_EXCP_STOP;
3404
    }
J
j_mayer 已提交
3405 3406 3407 3408
#endif
}
#endif

B
bellard 已提交
3409 3410
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
{
3411
#if defined(CONFIG_USER_ONLY)
3412
    GEN_EXCP_PRIVREG(ctx);
3413
#else
3414
    if (unlikely(!ctx->supervisor)) {
3415
        GEN_EXCP_PRIVREG(ctx);
3416
        return;
3417
    }
A
aurel32 已提交
3418
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3419 3420 3421 3422
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
        gen_op_update_riee();
    } else {
3423 3424 3425 3426
        /* 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
         */
3427
        gen_update_nip(ctx, ctx->nip);
3428
#if defined(TARGET_PPC64)
3429
        if (!ctx->sf_mode)
A
aurel32 已提交
3430
            gen_op_store_msr_32();
3431
        else
3432
#endif
A
aurel32 已提交
3433
            gen_op_store_msr();
3434 3435
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsrd is not always defined as context-synchronizing */
3436
        ctx->exception = POWERPC_EXCP_STOP;
3437
    }
3438
#endif
B
bellard 已提交
3439 3440 3441 3442 3443
}

/* mtspr */
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
{
3444
    void (*write_cb)(void *opaque, int sprn);
B
bellard 已提交
3445 3446
    uint32_t sprn = SPR(ctx->opcode);

3447
#if !defined(CONFIG_USER_ONLY)
3448 3449
    if (ctx->supervisor == 2)
        write_cb = ctx->spr_cb[sprn].hea_write;
3450
    else if (ctx->supervisor)
3451 3452
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
3453
#endif
3454
        write_cb = ctx->spr_cb[sprn].uea_write;
3455 3456
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
A
aurel32 已提交
3457
            tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3458 3459 3460
            (*write_cb)(ctx, sprn);
        } else {
            /* Privilege exception */
J
j_mayer 已提交
3461
            if (loglevel != 0) {
J
j_mayer 已提交
3462 3463
                fprintf(logfile, "Trying to write privileged spr %d %03x at "
                        ADDRX "\n", sprn, sprn, ctx->nip);
3464
            }
J
j_mayer 已提交
3465 3466
            printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
                   sprn, sprn, ctx->nip);
3467
            GEN_EXCP_PRIVREG(ctx);
3468
        }
3469 3470
    } else {
        /* Not defined */
J
j_mayer 已提交
3471
        if (loglevel != 0) {
J
j_mayer 已提交
3472 3473
            fprintf(logfile, "Trying to write invalid spr %d %03x at "
                    ADDRX "\n", sprn, sprn, ctx->nip);
3474
        }
J
j_mayer 已提交
3475 3476
        printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
               sprn, sprn, ctx->nip);
3477 3478
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3479 3480 3481 3482 3483
    }
}

/***                         Cache management                              ***/
/* dcbf */
3484
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
B
bellard 已提交
3485
{
J
j_mayer 已提交
3486
    /* XXX: specification says this is treated as a load by the MMU */
3487
    gen_addr_reg_index(ctx);
3488
    op_ldst(lbz);
B
bellard 已提交
3489 3490 3491
}

/* dcbi (Supervisor only) */
3492
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
B
bellard 已提交
3493
{
3494
#if defined(CONFIG_USER_ONLY)
3495
    GEN_EXCP_PRIVOPC(ctx);
3496
#else
3497
    if (unlikely(!ctx->supervisor)) {
3498
        GEN_EXCP_PRIVOPC(ctx);
3499
        return;
3500
    }
3501 3502
    gen_addr_reg_index(ctx);
    /* XXX: specification says this should be treated as a store by the MMU */
J
j_mayer 已提交
3503
    op_ldst(lbz);
3504 3505
    op_ldst(stb);
#endif
B
bellard 已提交
3506 3507 3508
}

/* dcdst */
3509
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
B
bellard 已提交
3510
{
3511 3512
    /* XXX: specification say this is treated as a load by the MMU */
    gen_addr_reg_index(ctx);
3513
    op_ldst(lbz);
B
bellard 已提交
3514 3515 3516
}

/* dcbt */
3517
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
B
bellard 已提交
3518
{
3519
    /* interpreted as no-op */
3520 3521 3522
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
3523 3524 3525
}

/* dcbtst */
3526
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
B
bellard 已提交
3527
{
3528
    /* interpreted as no-op */
3529 3530 3531
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
3532 3533 3534
}

/* dcbz */
3535
#define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
3536 3537
static GenOpFunc *gen_op_dcbz[4][NB_MEM_FUNCS] = {
    /* 32 bytes cache line size */
3538
    {
3539 3540 3541 3542 3543 3544 3545 3546 3547
#define gen_op_dcbz_l32_le_raw        gen_op_dcbz_l32_raw
#define gen_op_dcbz_l32_le_user       gen_op_dcbz_l32_user
#define gen_op_dcbz_l32_le_kernel     gen_op_dcbz_l32_kernel
#define gen_op_dcbz_l32_le_hypv       gen_op_dcbz_l32_hypv
#define gen_op_dcbz_l32_le_64_raw     gen_op_dcbz_l32_64_raw
#define gen_op_dcbz_l32_le_64_user    gen_op_dcbz_l32_64_user
#define gen_op_dcbz_l32_le_64_kernel  gen_op_dcbz_l32_64_kernel
#define gen_op_dcbz_l32_le_64_hypv    gen_op_dcbz_l32_64_hypv
        GEN_MEM_FUNCS(dcbz_l32),
3548
    },
3549
    /* 64 bytes cache line size */
3550
    {
3551 3552 3553 3554 3555 3556 3557 3558 3559
#define gen_op_dcbz_l64_le_raw        gen_op_dcbz_l64_raw
#define gen_op_dcbz_l64_le_user       gen_op_dcbz_l64_user
#define gen_op_dcbz_l64_le_kernel     gen_op_dcbz_l64_kernel
#define gen_op_dcbz_l64_le_hypv       gen_op_dcbz_l64_hypv
#define gen_op_dcbz_l64_le_64_raw     gen_op_dcbz_l64_64_raw
#define gen_op_dcbz_l64_le_64_user    gen_op_dcbz_l64_64_user
#define gen_op_dcbz_l64_le_64_kernel  gen_op_dcbz_l64_64_kernel
#define gen_op_dcbz_l64_le_64_hypv    gen_op_dcbz_l64_64_hypv
        GEN_MEM_FUNCS(dcbz_l64),
3560
    },
3561
    /* 128 bytes cache line size */
3562
    {
3563 3564 3565 3566 3567 3568 3569 3570 3571
#define gen_op_dcbz_l128_le_raw       gen_op_dcbz_l128_raw
#define gen_op_dcbz_l128_le_user      gen_op_dcbz_l128_user
#define gen_op_dcbz_l128_le_kernel    gen_op_dcbz_l128_kernel
#define gen_op_dcbz_l128_le_hypv      gen_op_dcbz_l128_hypv
#define gen_op_dcbz_l128_le_64_raw    gen_op_dcbz_l128_64_raw
#define gen_op_dcbz_l128_le_64_user   gen_op_dcbz_l128_64_user
#define gen_op_dcbz_l128_le_64_kernel gen_op_dcbz_l128_64_kernel
#define gen_op_dcbz_l128_le_64_hypv   gen_op_dcbz_l128_64_hypv
        GEN_MEM_FUNCS(dcbz_l128),
3572
    },
3573
    /* tunable cache line size */
3574
    {
3575 3576 3577 3578 3579 3580 3581 3582 3583
#define gen_op_dcbz_le_raw            gen_op_dcbz_raw
#define gen_op_dcbz_le_user           gen_op_dcbz_user
#define gen_op_dcbz_le_kernel         gen_op_dcbz_kernel
#define gen_op_dcbz_le_hypv           gen_op_dcbz_hypv
#define gen_op_dcbz_le_64_raw         gen_op_dcbz_64_raw
#define gen_op_dcbz_le_64_user        gen_op_dcbz_64_user
#define gen_op_dcbz_le_64_kernel      gen_op_dcbz_64_kernel
#define gen_op_dcbz_le_64_hypv        gen_op_dcbz_64_hypv
        GEN_MEM_FUNCS(dcbz),
3584
    },
3585
};
3586

3587 3588
static always_inline void handler_dcbz (DisasContext *ctx,
                                        int dcache_line_size)
3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609
{
    int n;

    switch (dcache_line_size) {
    case 32:
        n = 0;
        break;
    case 64:
        n = 1;
        break;
    case 128:
        n = 2;
        break;
    default:
        n = 3;
        break;
    }
    op_dcbz(n);
}

GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
B
bellard 已提交
3610
{
3611
    gen_addr_reg_index(ctx);
3612 3613 3614 3615
    handler_dcbz(ctx, ctx->dcache_line_size);
    gen_op_check_reservation();
}

3616
GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
3617 3618 3619 3620 3621 3622
{
    gen_addr_reg_index(ctx);
    if (ctx->opcode & 0x00200000)
        handler_dcbz(ctx, ctx->dcache_line_size);
    else
        handler_dcbz(ctx, -1);
B
bellard 已提交
3623
    gen_op_check_reservation();
B
bellard 已提交
3624 3625 3626
}

/* icbi */
3627
#define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
3628 3629 3630 3631 3632 3633 3634 3635 3636 3637
#define gen_op_icbi_le_raw       gen_op_icbi_raw
#define gen_op_icbi_le_user      gen_op_icbi_user
#define gen_op_icbi_le_kernel    gen_op_icbi_kernel
#define gen_op_icbi_le_hypv      gen_op_icbi_hypv
#define gen_op_icbi_le_64_raw    gen_op_icbi_64_raw
#define gen_op_icbi_le_64_user   gen_op_icbi_64_user
#define gen_op_icbi_le_64_kernel gen_op_icbi_64_kernel
#define gen_op_icbi_le_64_hypv   gen_op_icbi_64_hypv
static GenOpFunc *gen_op_icbi[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(icbi),
3638
};
3639

3640
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
B
bellard 已提交
3641
{
3642 3643
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3644
    gen_addr_reg_index(ctx);
3645
    op_icbi();
B
bellard 已提交
3646 3647 3648 3649
}

/* Optional: */
/* dcba */
3650
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
B
bellard 已提交
3651
{
3652 3653 3654 3655
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
3656 3657 3658 3659 3660 3661 3662
}

/***                    Segment register manipulation                      ***/
/* Supervisor only: */
/* mfsr */
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
{
3663
#if defined(CONFIG_USER_ONLY)
3664
    GEN_EXCP_PRIVREG(ctx);
3665
#else
3666
    if (unlikely(!ctx->supervisor)) {
3667
        GEN_EXCP_PRIVREG(ctx);
3668
        return;
3669
    }
3670
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3671
    gen_op_load_sr();
A
aurel32 已提交
3672
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3673
#endif
B
bellard 已提交
3674 3675 3676
}

/* mfsrin */
3677
GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
B
bellard 已提交
3678
{
3679
#if defined(CONFIG_USER_ONLY)
3680
    GEN_EXCP_PRIVREG(ctx);
3681
#else
3682
    if (unlikely(!ctx->supervisor)) {
3683
        GEN_EXCP_PRIVREG(ctx);
3684
        return;
3685
    }
A
aurel32 已提交
3686
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3687 3688
    gen_op_srli_T1(28);
    gen_op_load_sr();
A
aurel32 已提交
3689
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3690
#endif
B
bellard 已提交
3691 3692 3693
}

/* mtsr */
B
bellard 已提交
3694
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
B
bellard 已提交
3695
{
3696
#if defined(CONFIG_USER_ONLY)
3697
    GEN_EXCP_PRIVREG(ctx);
3698
#else
3699
    if (unlikely(!ctx->supervisor)) {
3700
        GEN_EXCP_PRIVREG(ctx);
3701
        return;
3702
    }
A
aurel32 已提交
3703
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3704
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3705
    gen_op_store_sr();
3706
#endif
B
bellard 已提交
3707 3708 3709
}

/* mtsrin */
3710
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
B
bellard 已提交
3711
{
3712
#if defined(CONFIG_USER_ONLY)
3713
    GEN_EXCP_PRIVREG(ctx);
3714
#else
3715
    if (unlikely(!ctx->supervisor)) {
3716
        GEN_EXCP_PRIVREG(ctx);
3717
        return;
3718
    }
A
aurel32 已提交
3719 3720
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3721 3722
    gen_op_srli_T1(28);
    gen_op_store_sr();
3723
#endif
B
bellard 已提交
3724 3725
}

3726 3727 3728
#if defined(TARGET_PPC64)
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
/* mfsr */
3729
GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
3730 3731 3732 3733 3734 3735 3736 3737
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
3738
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3739
    gen_op_load_slb();
A
aurel32 已提交
3740
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3741 3742 3743 3744
#endif
}

/* mfsrin */
3745 3746
GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
             PPC_SEGMENT_64B)
3747 3748 3749 3750 3751 3752 3753 3754
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
A
aurel32 已提交
3755
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3756 3757
    gen_op_srli_T1(28);
    gen_op_load_slb();
A
aurel32 已提交
3758
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3759 3760 3761 3762
#endif
}

/* mtsr */
3763
GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
3764 3765 3766 3767 3768 3769 3770 3771
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
A
aurel32 已提交
3772
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3773
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3774 3775 3776 3777 3778
    gen_op_store_slb();
#endif
}

/* mtsrin */
3779 3780
GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
             PPC_SEGMENT_64B)
3781 3782 3783 3784 3785 3786 3787 3788
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
A
aurel32 已提交
3789 3790
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3791 3792 3793 3794 3795 3796
    gen_op_srli_T1(28);
    gen_op_store_slb();
#endif
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3797 3798 3799
/***                      Lookaside buffer management                      ***/
/* Optional & supervisor only: */
/* tlbia */
3800
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
B
bellard 已提交
3801
{
3802
#if defined(CONFIG_USER_ONLY)
3803
    GEN_EXCP_PRIVOPC(ctx);
3804
#else
3805
    if (unlikely(!ctx->supervisor)) {
3806
        GEN_EXCP_PRIVOPC(ctx);
3807
        return;
3808 3809 3810
    }
    gen_op_tlbia();
#endif
B
bellard 已提交
3811 3812 3813
}

/* tlbie */
3814
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
B
bellard 已提交
3815
{
3816
#if defined(CONFIG_USER_ONLY)
3817
    GEN_EXCP_PRIVOPC(ctx);
3818
#else
3819
    if (unlikely(!ctx->supervisor)) {
3820
        GEN_EXCP_PRIVOPC(ctx);
3821
        return;
3822
    }
A
aurel32 已提交
3823
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
3824 3825 3826 3827 3828 3829
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_tlbie_64();
    else
#endif
        gen_op_tlbie();
3830
#endif
B
bellard 已提交
3831 3832 3833
}

/* tlbsync */
3834
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
B
bellard 已提交
3835
{
3836
#if defined(CONFIG_USER_ONLY)
3837
    GEN_EXCP_PRIVOPC(ctx);
3838
#else
3839
    if (unlikely(!ctx->supervisor)) {
3840
        GEN_EXCP_PRIVOPC(ctx);
3841
        return;
3842 3843 3844 3845
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
3846
    GEN_STOP(ctx);
3847
#endif
B
bellard 已提交
3848 3849
}

J
j_mayer 已提交
3850 3851 3852 3853 3854
#if defined(TARGET_PPC64)
/* slbia */
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
{
#if defined(CONFIG_USER_ONLY)
3855
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3856 3857
#else
    if (unlikely(!ctx->supervisor)) {
3858
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3859 3860 3861 3862 3863 3864 3865 3866 3867 3868
        return;
    }
    gen_op_slbia();
#endif
}

/* slbie */
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
{
#if defined(CONFIG_USER_ONLY)
3869
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3870 3871
#else
    if (unlikely(!ctx->supervisor)) {
3872
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3873 3874
        return;
    }
A
aurel32 已提交
3875
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
J
j_mayer 已提交
3876 3877 3878 3879 3880
    gen_op_slbie();
#endif
}
#endif

B
bellard 已提交
3881 3882
/***                              External control                         ***/
/* Optional: */
3883 3884
#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
3885 3886
static GenOpFunc *gen_op_eciwx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(eciwx),
3887
};
3888 3889
static GenOpFunc *gen_op_ecowx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(ecowx),
3890
};
3891

3892
/* eciwx */
B
bellard 已提交
3893 3894
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
{
3895
    /* Should check EAR[E] & alignment ! */
3896 3897
    gen_addr_reg_index(ctx);
    op_eciwx();
A
aurel32 已提交
3898
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3899 3900 3901 3902 3903 3904 3905
}

/* ecowx */
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
{
    /* Should check EAR[E] & alignment ! */
    gen_addr_reg_index(ctx);
A
aurel32 已提交
3906
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
3907 3908 3909 3910 3911 3912 3913
    op_ecowx();
}

/* PowerPC 601 specific instructions */
/* abs - abs. */
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
{
A
aurel32 已提交
3914
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3915
    gen_op_POWER_abs();
A
aurel32 已提交
3916
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3917 3918 3919 3920 3921 3922 3923
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* abso - abso. */
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
{
A
aurel32 已提交
3924
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3925
    gen_op_POWER_abso();
A
aurel32 已提交
3926
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3927 3928 3929 3930 3931
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* clcs */
3932
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
3933
{
A
aurel32 已提交
3934
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3935
    gen_op_POWER_clcs();
3936
    /* Rc=1 sets CR0 to an undefined state */
A
aurel32 已提交
3937
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3938 3939 3940 3941 3942
}

/* div - div. */
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
3943 3944
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3945
    gen_op_POWER_div();
A
aurel32 已提交
3946
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3947 3948 3949 3950 3951 3952 3953
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* divo - divo. */
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
3954 3955
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3956
    gen_op_POWER_divo();
A
aurel32 已提交
3957
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3958 3959 3960 3961 3962 3963 3964
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* divs - divs. */
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
3965 3966
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3967
    gen_op_POWER_divs();
A
aurel32 已提交
3968
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3969 3970 3971 3972 3973 3974 3975
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* divso - divso. */
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
3976 3977
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3978
    gen_op_POWER_divso();
A
aurel32 已提交
3979
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3980 3981 3982 3983 3984 3985 3986
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* doz - doz. */
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
3987 3988
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3989
    gen_op_POWER_doz();
A
aurel32 已提交
3990
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3991 3992 3993 3994 3995 3996 3997
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* dozo - dozo. */
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
3998 3999
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4000
    gen_op_POWER_dozo();
A
aurel32 已提交
4001
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4002 4003 4004 4005 4006 4007 4008
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* dozi */
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4009
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4010
    tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
4011
    gen_op_POWER_doz();
A
aurel32 已提交
4012
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4013 4014
}

4015 4016 4017
/* As lscbx load from memory byte after byte, it's always endian safe.
 * Original POWER is 32 bits only, define 64 bits ops as 32 bits ones
 */
4018
#define op_POWER_lscbx(start, ra, rb)                                         \
4019
(*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033
#define gen_op_POWER_lscbx_64_raw       gen_op_POWER_lscbx_raw
#define gen_op_POWER_lscbx_64_user      gen_op_POWER_lscbx_user
#define gen_op_POWER_lscbx_64_kernel    gen_op_POWER_lscbx_kernel
#define gen_op_POWER_lscbx_64_hypv      gen_op_POWER_lscbx_hypv
#define gen_op_POWER_lscbx_le_raw       gen_op_POWER_lscbx_raw
#define gen_op_POWER_lscbx_le_user      gen_op_POWER_lscbx_user
#define gen_op_POWER_lscbx_le_kernel    gen_op_POWER_lscbx_kernel
#define gen_op_POWER_lscbx_le_hypv      gen_op_POWER_lscbx_hypv
#define gen_op_POWER_lscbx_le_64_raw    gen_op_POWER_lscbx_raw
#define gen_op_POWER_lscbx_le_64_user   gen_op_POWER_lscbx_user
#define gen_op_POWER_lscbx_le_64_kernel gen_op_POWER_lscbx_kernel
#define gen_op_POWER_lscbx_le_64_hypv   gen_op_POWER_lscbx_hypv
static GenOpFunc3 *gen_op_POWER_lscbx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(POWER_lscbx),
4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046
};

/* lscbx - lscbx. */
GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
{
    int ra = rA(ctx->opcode);
    int rb = rB(ctx->opcode);

    gen_addr_reg_index(ctx);
    if (ra == 0) {
        ra = rb;
    }
    /* NIP cannot be restored if the memory exception comes from an helper */
4047
    gen_update_nip(ctx, ctx->nip - 4);
4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058
    gen_op_load_xer_bc();
    gen_op_load_xer_cmp();
    op_POWER_lscbx(rD(ctx->opcode), ra, rb);
    gen_op_store_xer_bc();
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* maskg - maskg. */
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4059 4060
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4061
    gen_op_POWER_maskg();
A
aurel32 已提交
4062
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4063 4064 4065 4066 4067 4068 4069
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* maskir - maskir. */
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4070 4071 4072
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4073
    gen_op_POWER_maskir();
A
aurel32 已提交
4074
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4075 4076 4077 4078 4079 4080 4081
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* mul - mul. */
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4082 4083
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4084
    gen_op_POWER_mul();
A
aurel32 已提交
4085
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4086 4087 4088 4089 4090 4091 4092
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* mulo - mulo. */
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4093 4094
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4095
    gen_op_POWER_mulo();
A
aurel32 已提交
4096
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4097 4098 4099 4100 4101 4102 4103
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* nabs - nabs. */
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4104
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4105
    gen_op_POWER_nabs();
A
aurel32 已提交
4106
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4107 4108 4109 4110 4111 4112 4113
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* nabso - nabso. */
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4114
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4115
    gen_op_POWER_nabso();
A
aurel32 已提交
4116
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* rlmi - rlmi. */
GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
{
    uint32_t mb, me;

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
A
aurel32 已提交
4128 4129 4130
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4131
    gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
A
aurel32 已提交
4132
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4133 4134 4135 4136 4137 4138 4139
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* rrib - rrib. */
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4140 4141 4142
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4143
    gen_op_POWER_rrib();
A
aurel32 已提交
4144
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4145 4146 4147 4148 4149 4150 4151
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sle - sle. */
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4152 4153
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4154
    gen_op_POWER_sle();
A
aurel32 已提交
4155
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4156 4157 4158 4159 4160 4161 4162
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sleq - sleq. */
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4163 4164
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4165
    gen_op_POWER_sleq();
A
aurel32 已提交
4166
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4167 4168 4169 4170 4171 4172 4173
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sliq - sliq. */
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4174
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4175
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4176
    gen_op_POWER_sle();
A
aurel32 已提交
4177
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4178 4179 4180 4181 4182 4183 4184
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* slliq - slliq. */
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4185
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4186
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4187
    gen_op_POWER_sleq();
A
aurel32 已提交
4188
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4189 4190 4191 4192 4193 4194 4195
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sllq - sllq. */
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4196 4197
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4198
    gen_op_POWER_sllq();
A
aurel32 已提交
4199
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4200 4201 4202 4203 4204 4205 4206
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* slq - slq. */
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4207 4208
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4209
    gen_op_POWER_slq();
A
aurel32 已提交
4210
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4211 4212 4213 4214
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

4215
/* sraiq - sraiq. */
4216 4217
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4218
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4219
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4220
    gen_op_POWER_sraq();
A
aurel32 已提交
4221
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4222 4223 4224 4225 4226 4227 4228
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sraq - sraq. */
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4229 4230
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4231
    gen_op_POWER_sraq();
A
aurel32 已提交
4232
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4233 4234 4235 4236 4237 4238 4239
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sre - sre. */
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4240 4241
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4242
    gen_op_POWER_sre();
A
aurel32 已提交
4243
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4244 4245 4246 4247 4248 4249 4250
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* srea - srea. */
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4251 4252
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4253
    gen_op_POWER_srea();
A
aurel32 已提交
4254
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4255 4256 4257 4258 4259 4260 4261
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sreq */
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4262 4263
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4264
    gen_op_POWER_sreq();
A
aurel32 已提交
4265
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4266 4267 4268 4269 4270 4271 4272
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sriq */
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4273
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4274
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4275
    gen_op_POWER_srq();
A
aurel32 已提交
4276
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4277 4278 4279 4280 4281 4282 4283
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* srliq */
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4284 4285
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4286
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4287
    gen_op_POWER_srlq();
A
aurel32 已提交
4288
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4289 4290 4291 4292 4293 4294 4295
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* srlq */
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4296 4297
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4298
    gen_op_POWER_srlq();
A
aurel32 已提交
4299
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4300 4301 4302 4303 4304 4305 4306
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* srq */
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4307 4308
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4309
    gen_op_POWER_srq();
A
aurel32 已提交
4310
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4311 4312 4313 4314 4315 4316 4317 4318 4319
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* PowerPC 602 specific instructions */
/* dsa  */
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4320
    GEN_EXCP_INVAL(ctx);
4321 4322 4323 4324 4325 4326
}

/* esa */
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4327
    GEN_EXCP_INVAL(ctx);
4328 4329 4330 4331 4332 4333
}

/* mfrom */
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
{
#if defined(CONFIG_USER_ONLY)
4334
    GEN_EXCP_PRIVOPC(ctx);
4335 4336
#else
    if (unlikely(!ctx->supervisor)) {
4337
        GEN_EXCP_PRIVOPC(ctx);
4338 4339
        return;
    }
A
aurel32 已提交
4340
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4341
    gen_op_602_mfrom();
A
aurel32 已提交
4342
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4343 4344 4345 4346 4347
#endif
}

/* 602 - 603 - G2 TLB management */
/* tlbld */
4348
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
4349 4350
{
#if defined(CONFIG_USER_ONLY)
4351
    GEN_EXCP_PRIVOPC(ctx);
4352 4353
#else
    if (unlikely(!ctx->supervisor)) {
4354
        GEN_EXCP_PRIVOPC(ctx);
4355 4356
        return;
    }
A
aurel32 已提交
4357
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4358 4359 4360 4361 4362
    gen_op_6xx_tlbld();
#endif
}

/* tlbli */
4363
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
4364 4365
{
#if defined(CONFIG_USER_ONLY)
4366
    GEN_EXCP_PRIVOPC(ctx);
4367 4368
#else
    if (unlikely(!ctx->supervisor)) {
4369
        GEN_EXCP_PRIVOPC(ctx);
4370 4371
        return;
    }
A
aurel32 已提交
4372
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4373 4374 4375 4376
    gen_op_6xx_tlbli();
#endif
}

4377 4378
/* 74xx TLB management */
/* tlbld */
4379
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
4380 4381 4382 4383 4384 4385 4386 4387
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
A
aurel32 已提交
4388
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4389 4390 4391 4392 4393
    gen_op_74xx_tlbld();
#endif
}

/* tlbli */
4394
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
4395 4396 4397 4398 4399 4400 4401 4402
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
A
aurel32 已提交
4403
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4404 4405 4406 4407
    gen_op_74xx_tlbli();
#endif
}

4408 4409 4410 4411 4412 4413 4414 4415 4416 4417
/* 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 已提交
4418
    /* Cache line invalidate: privileged and treated as no-op */
4419
#if defined(CONFIG_USER_ONLY)
4420
    GEN_EXCP_PRIVOPC(ctx);
4421 4422
#else
    if (unlikely(!ctx->supervisor)) {
4423
        GEN_EXCP_PRIVOPC(ctx);
4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437
        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)
4438
    GEN_EXCP_PRIVOPC(ctx);
4439 4440
#else
    if (unlikely(!ctx->supervisor)) {
4441
        GEN_EXCP_PRIVOPC(ctx);
4442 4443 4444 4445 4446 4447 4448
        return;
    }
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);

    gen_addr_reg_index(ctx);
    gen_op_POWER_mfsri();
A
aurel32 已提交
4449
    tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
4450
    if (ra != 0 && ra != rd)
A
aurel32 已提交
4451
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
4452 4453 4454 4455 4456 4457
#endif
}

GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
4458
    GEN_EXCP_PRIVOPC(ctx);
4459 4460
#else
    if (unlikely(!ctx->supervisor)) {
4461
        GEN_EXCP_PRIVOPC(ctx);
4462 4463 4464 4465
        return;
    }
    gen_addr_reg_index(ctx);
    gen_op_POWER_rac();
A
aurel32 已提交
4466
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4467 4468 4469 4470 4471 4472
#endif
}

GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
4473
    GEN_EXCP_PRIVOPC(ctx);
4474 4475
#else
    if (unlikely(!ctx->supervisor)) {
4476
        GEN_EXCP_PRIVOPC(ctx);
4477 4478 4479
        return;
    }
    gen_op_POWER_rfsvc();
4480
    GEN_SYNC(ctx);
4481 4482 4483 4484 4485 4486 4487
#endif
}

/* svc is not implemented for now */

/* POWER2 specific instructions */
/* Quad manipulation (load/store two floats at a time) */
4488
/* Original POWER2 is 32 bits only, define 64 bits ops as 32 bits ones */
4489 4490
#define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
#define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508
#define gen_op_POWER2_lfq_64_raw        gen_op_POWER2_lfq_raw
#define gen_op_POWER2_lfq_64_user       gen_op_POWER2_lfq_user
#define gen_op_POWER2_lfq_64_kernel     gen_op_POWER2_lfq_kernel
#define gen_op_POWER2_lfq_64_hypv       gen_op_POWER2_lfq_hypv
#define gen_op_POWER2_lfq_le_64_raw     gen_op_POWER2_lfq_le_raw
#define gen_op_POWER2_lfq_le_64_user    gen_op_POWER2_lfq_le_user
#define gen_op_POWER2_lfq_le_64_kernel  gen_op_POWER2_lfq_le_kernel
#define gen_op_POWER2_lfq_le_64_hypv    gen_op_POWER2_lfq_le_hypv
#define gen_op_POWER2_stfq_64_raw       gen_op_POWER2_stfq_raw
#define gen_op_POWER2_stfq_64_user      gen_op_POWER2_stfq_user
#define gen_op_POWER2_stfq_64_kernel    gen_op_POWER2_stfq_kernel
#define gen_op_POWER2_stfq_64_hypv      gen_op_POWER2_stfq_hypv
#define gen_op_POWER2_stfq_le_64_raw    gen_op_POWER2_stfq_le_raw
#define gen_op_POWER2_stfq_le_64_user   gen_op_POWER2_stfq_le_user
#define gen_op_POWER2_stfq_le_64_kernel gen_op_POWER2_stfq_le_kernel
#define gen_op_POWER2_stfq_le_64_hypv   gen_op_POWER2_stfq_le_hypv
static GenOpFunc *gen_op_POWER2_lfq[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(POWER2_lfq),
4509
};
4510 4511
static GenOpFunc *gen_op_POWER2_stfq[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(POWER2_stfq),
4512 4513 4514 4515 4516 4517
};

/* lfq */
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
4518
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
4519
    gen_addr_imm_index(ctx, 0);
4520
    op_POWER2_lfq();
A
aurel32 已提交
4521 4522
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
4523 4524 4525 4526 4527 4528 4529 4530
}

/* lfqu */
GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    int ra = rA(ctx->opcode);

    /* NIP cannot be restored if the memory exception comes from an helper */
4531
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
4532
    gen_addr_imm_index(ctx, 0);
4533
    op_POWER2_lfq();
A
aurel32 已提交
4534 4535
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
4536
    if (ra != 0)
A
aurel32 已提交
4537
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4538 4539 4540 4541 4542 4543 4544 4545
}

/* lfqux */
GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
{
    int ra = rA(ctx->opcode);

    /* NIP cannot be restored if the memory exception comes from an helper */
4546
    gen_update_nip(ctx, ctx->nip - 4);
4547 4548
    gen_addr_reg_index(ctx);
    op_POWER2_lfq();
A
aurel32 已提交
4549 4550
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
4551
    if (ra != 0)
A
aurel32 已提交
4552
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4553 4554 4555 4556 4557 4558
}

/* lfqx */
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
4559
    gen_update_nip(ctx, ctx->nip - 4);
4560 4561
    gen_addr_reg_index(ctx);
    op_POWER2_lfq();
A
aurel32 已提交
4562 4563
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
4564 4565 4566 4567 4568 4569
}

/* stfq */
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
4570
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
4571
    gen_addr_imm_index(ctx, 0);
A
aurel32 已提交
4572 4573
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
4574 4575 4576 4577 4578 4579 4580 4581 4582
    op_POWER2_stfq();
}

/* stfqu */
GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    int ra = rA(ctx->opcode);

    /* NIP cannot be restored if the memory exception comes from an helper */
4583
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
4584
    gen_addr_imm_index(ctx, 0);
A
aurel32 已提交
4585 4586
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
4587 4588
    op_POWER2_stfq();
    if (ra != 0)
A
aurel32 已提交
4589
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4590 4591 4592 4593 4594 4595 4596 4597
}

/* stfqux */
GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
{
    int ra = rA(ctx->opcode);

    /* NIP cannot be restored if the memory exception comes from an helper */
4598
    gen_update_nip(ctx, ctx->nip - 4);
4599
    gen_addr_reg_index(ctx);
A
aurel32 已提交
4600 4601
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
4602 4603
    op_POWER2_stfq();
    if (ra != 0)
A
aurel32 已提交
4604
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4605 4606 4607 4608 4609 4610
}

/* stfqx */
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
4611
    gen_update_nip(ctx, ctx->nip - 4);
4612
    gen_addr_reg_index(ctx);
A
aurel32 已提交
4613 4614
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
4615 4616 4617 4618
    op_POWER2_stfq();
}

/* BookE specific instructions */
4619
/* XXX: not implemented on 440 ? */
4620
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
4621 4622
{
    /* XXX: TODO */
4623
    GEN_EXCP_INVAL(ctx);
4624 4625
}

4626
/* XXX: not implemented on 440 ? */
4627
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
4628 4629
{
#if defined(CONFIG_USER_ONLY)
4630
    GEN_EXCP_PRIVOPC(ctx);
4631 4632
#else
    if (unlikely(!ctx->supervisor)) {
4633
        GEN_EXCP_PRIVOPC(ctx);
4634 4635 4636 4637
        return;
    }
    gen_addr_reg_index(ctx);
    /* Use the same micro-ops as for tlbie */
4638 4639 4640 4641 4642 4643
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_tlbie_64();
    else
#endif
        gen_op_tlbie();
4644 4645 4646 4647
#endif
}

/* All 405 MAC instructions are translated here */
4648 4649 4650
static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
                                                int opc2, int opc3,
                                                int ra, int rb, int rt, int Rc)
4651
{
A
aurel32 已提交
4652 4653
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[ra]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rb]);
4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
        gen_op_405_mulchw();
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
        gen_op_405_mulchwu();
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
        gen_op_405_mulhhw();
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
        gen_op_405_mulhhwu();
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
        gen_op_405_mullhw();
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
        gen_op_405_mullhwu();
        break;
    }
    if (opc2 & 0x02) {
        /* nmultiply-and-accumulate (0x0E) */
        gen_op_neg();
    }
    if (opc2 & 0x04) {
        /* (n)multiply-and-accumulate (0x0C - 0x0E) */
A
aurel32 已提交
4704
        tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rt]);
4705
        tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
4706 4707 4708 4709 4710
        gen_op_405_add_T0_T2();
    }
    if (opc3 & 0x10) {
        /* Check overflow */
        if (opc3 & 0x01)
4711
            gen_op_check_addo();
4712 4713 4714 4715 4716 4717 4718 4719 4720 4721
        else
            gen_op_405_check_ovu();
    }
    if (opc3 & 0x02) {
        /* Saturate */
        if (opc3 & 0x01)
            gen_op_405_check_sat();
        else
            gen_op_405_check_satu();
    }
A
aurel32 已提交
4722
    tcg_gen_mov_tl(cpu_gpr[rt], cpu_T[0]);
4723 4724 4725 4726 4727 4728
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
        gen_set_Rc0(ctx);
    }
}

4729 4730
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)                  \
4731 4732 4733 4734 4735 4736
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
4737
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
4738
/* macchwo   - macchwo.   */
4739
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
4740
/* macchws   - macchws.   */
4741
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
4742
/* macchwso  - macchwso.  */
4743
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
4744
/* macchwsu  - macchwsu.  */
4745
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
4746
/* macchwsuo - macchwsuo. */
4747
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
4748
/* macchwu   - macchwu.   */
4749
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
4750
/* macchwuo  - macchwuo.  */
4751
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
4752
/* machhw    - machhw.    */
4753
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
4754
/* machhwo   - machhwo.   */
4755
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
4756
/* machhws   - machhws.   */
4757
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
4758
/* machhwso  - machhwso.  */
4759
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
4760
/* machhwsu  - machhwsu.  */
4761
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
4762
/* machhwsuo - machhwsuo. */
4763
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
4764
/* machhwu   - machhwu.   */
4765
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
4766
/* machhwuo  - machhwuo.  */
4767
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
4768
/* maclhw    - maclhw.    */
4769
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
4770
/* maclhwo   - maclhwo.   */
4771
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
4772
/* maclhws   - maclhws.   */
4773
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
4774
/* maclhwso  - maclhwso.  */
4775
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
4776
/* maclhwu   - maclhwu.   */
4777
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
4778
/* maclhwuo  - maclhwuo.  */
4779
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
4780
/* maclhwsu  - maclhwsu.  */
4781
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
4782
/* maclhwsuo - maclhwsuo. */
4783
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
4784
/* nmacchw   - nmacchw.   */
4785
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
4786
/* nmacchwo  - nmacchwo.  */
4787
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
4788
/* nmacchws  - nmacchws.  */
4789
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
4790
/* nmacchwso - nmacchwso. */
4791
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
4792
/* nmachhw   - nmachhw.   */
4793
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
4794
/* nmachhwo  - nmachhwo.  */
4795
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
4796
/* nmachhws  - nmachhws.  */
4797
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
4798
/* nmachhwso - nmachhwso. */
4799
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
4800
/* nmaclhw   - nmaclhw.   */
4801
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
4802
/* nmaclhwo  - nmaclhwo.  */
4803
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
4804
/* nmaclhws  - nmaclhws.  */
4805
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
4806
/* nmaclhwso - nmaclhwso. */
4807
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
4808 4809

/* mulchw  - mulchw.  */
4810
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
4811
/* mulchwu - mulchwu. */
4812
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
4813
/* mulhhw  - mulhhw.  */
4814
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
4815
/* mulhhwu - mulhhwu. */
4816
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
4817
/* mullhw  - mullhw.  */
4818
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
4819
/* mullhwu - mullhwu. */
4820
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
4821 4822

/* mfdcr */
4823
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
4824 4825
{
#if defined(CONFIG_USER_ONLY)
4826
    GEN_EXCP_PRIVREG(ctx);
4827 4828 4829 4830
#else
    uint32_t dcrn = SPR(ctx->opcode);

    if (unlikely(!ctx->supervisor)) {
4831
        GEN_EXCP_PRIVREG(ctx);
4832 4833
        return;
    }
4834
    tcg_gen_movi_tl(cpu_T[0], dcrn);
4835
    gen_op_load_dcr();
A
aurel32 已提交
4836
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4837 4838 4839 4840
#endif
}

/* mtdcr */
4841
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
4842 4843
{
#if defined(CONFIG_USER_ONLY)
4844
    GEN_EXCP_PRIVREG(ctx);
4845 4846 4847 4848
#else
    uint32_t dcrn = SPR(ctx->opcode);

    if (unlikely(!ctx->supervisor)) {
4849
        GEN_EXCP_PRIVREG(ctx);
4850 4851
        return;
    }
4852
    tcg_gen_movi_tl(cpu_T[0], dcrn);
A
aurel32 已提交
4853
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4854 4855 4856 4857 4858
    gen_op_store_dcr();
#endif
}

/* mfdcrx */
4859
/* XXX: not implemented on 440 ? */
4860
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
4861 4862
{
#if defined(CONFIG_USER_ONLY)
4863
    GEN_EXCP_PRIVREG(ctx);
4864 4865
#else
    if (unlikely(!ctx->supervisor)) {
4866
        GEN_EXCP_PRIVREG(ctx);
4867 4868
        return;
    }
A
aurel32 已提交
4869
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4870
    gen_op_load_dcr();
A
aurel32 已提交
4871
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4872
    /* Note: Rc update flag set leads to undefined state of Rc0 */
4873 4874 4875 4876
#endif
}

/* mtdcrx */
4877
/* XXX: not implemented on 440 ? */
4878
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
4879 4880
{
#if defined(CONFIG_USER_ONLY)
4881
    GEN_EXCP_PRIVREG(ctx);
4882 4883
#else
    if (unlikely(!ctx->supervisor)) {
4884
        GEN_EXCP_PRIVREG(ctx);
4885 4886
        return;
    }
A
aurel32 已提交
4887 4888
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4889
    gen_op_store_dcr();
4890
    /* Note: Rc update flag set leads to undefined state of Rc0 */
4891 4892 4893
#endif
}

4894 4895 4896
/* mfdcrux (PPC 460) : user-mode access to DCR */
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
{
A
aurel32 已提交
4897
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4898
    gen_op_load_dcr();
A
aurel32 已提交
4899
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4900 4901 4902 4903 4904 4905
    /* 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)
{
A
aurel32 已提交
4906 4907
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4908 4909 4910 4911
    gen_op_store_dcr();
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

4912 4913 4914 4915
/* dccci */
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
4916
    GEN_EXCP_PRIVOPC(ctx);
4917 4918
#else
    if (unlikely(!ctx->supervisor)) {
4919
        GEN_EXCP_PRIVOPC(ctx);
4920 4921 4922 4923 4924 4925 4926 4927 4928 4929
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
4930
    GEN_EXCP_PRIVOPC(ctx);
4931 4932
#else
    if (unlikely(!ctx->supervisor)) {
4933
        GEN_EXCP_PRIVOPC(ctx);
4934 4935 4936 4937
        return;
    }
    gen_addr_reg_index(ctx);
    op_ldst(lwz);
A
aurel32 已提交
4938
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4939 4940 4941 4942
#endif
}

/* icbt */
4943
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954
{
    /* 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)
4955
    GEN_EXCP_PRIVOPC(ctx);
4956 4957
#else
    if (unlikely(!ctx->supervisor)) {
4958
        GEN_EXCP_PRIVOPC(ctx);
4959 4960 4961 4962 4963 4964 4965 4966 4967 4968
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
4969
    GEN_EXCP_PRIVOPC(ctx);
4970 4971
#else
    if (unlikely(!ctx->supervisor)) {
4972
        GEN_EXCP_PRIVOPC(ctx);
4973 4974 4975 4976 4977 4978 4979
        return;
    }
    /* interpreted as no-op */
#endif
}

/* rfci (supervisor only) */
4980
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
4981 4982
{
#if defined(CONFIG_USER_ONLY)
4983
    GEN_EXCP_PRIVOPC(ctx);
4984 4985
#else
    if (unlikely(!ctx->supervisor)) {
4986
        GEN_EXCP_PRIVOPC(ctx);
4987 4988 4989 4990
        return;
    }
    /* Restore CPU state */
    gen_op_40x_rfci();
4991
    GEN_SYNC(ctx);
4992 4993 4994 4995 4996 4997
#endif
}

GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
{
#if defined(CONFIG_USER_ONLY)
4998
    GEN_EXCP_PRIVOPC(ctx);
4999 5000
#else
    if (unlikely(!ctx->supervisor)) {
5001
        GEN_EXCP_PRIVOPC(ctx);
5002 5003 5004 5005
        return;
    }
    /* Restore CPU state */
    gen_op_rfci();
5006
    GEN_SYNC(ctx);
5007 5008 5009 5010
#endif
}

/* BookE specific */
5011
/* XXX: not implemented on 440 ? */
5012
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
5013 5014
{
#if defined(CONFIG_USER_ONLY)
5015
    GEN_EXCP_PRIVOPC(ctx);
5016 5017
#else
    if (unlikely(!ctx->supervisor)) {
5018
        GEN_EXCP_PRIVOPC(ctx);
5019 5020 5021
        return;
    }
    /* Restore CPU state */
5022
    gen_op_rfdi();
5023
    GEN_SYNC(ctx);
5024 5025 5026
#endif
}

5027
/* XXX: not implemented on 440 ? */
5028
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
5029 5030
{
#if defined(CONFIG_USER_ONLY)
5031
    GEN_EXCP_PRIVOPC(ctx);
5032 5033
#else
    if (unlikely(!ctx->supervisor)) {
5034
        GEN_EXCP_PRIVOPC(ctx);
5035 5036 5037 5038
        return;
    }
    /* Restore CPU state */
    gen_op_rfmci();
5039
    GEN_SYNC(ctx);
5040 5041
#endif
}
5042

5043
/* TLB management - PowerPC 405 implementation */
5044
/* tlbre */
5045
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
5046 5047
{
#if defined(CONFIG_USER_ONLY)
5048
    GEN_EXCP_PRIVOPC(ctx);
5049 5050
#else
    if (unlikely(!ctx->supervisor)) {
5051
        GEN_EXCP_PRIVOPC(ctx);
5052 5053 5054 5055
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
A
aurel32 已提交
5056
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5057
        gen_op_4xx_tlbre_hi();
A
aurel32 已提交
5058
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5059 5060
        break;
    case 1:
A
aurel32 已提交
5061
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5062
        gen_op_4xx_tlbre_lo();
A
aurel32 已提交
5063
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5064 5065
        break;
    default:
5066
        GEN_EXCP_INVAL(ctx);
5067
        break;
5068
    }
5069 5070 5071
#endif
}

5072
/* tlbsx - tlbsx. */
5073
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5074 5075
{
#if defined(CONFIG_USER_ONLY)
5076
    GEN_EXCP_PRIVOPC(ctx);
5077 5078
#else
    if (unlikely(!ctx->supervisor)) {
5079
        GEN_EXCP_PRIVOPC(ctx);
5080 5081 5082
        return;
    }
    gen_addr_reg_index(ctx);
5083
    gen_op_4xx_tlbsx();
5084
    if (Rc(ctx->opcode))
5085
        gen_op_4xx_tlbsx_check();
A
aurel32 已提交
5086
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5087
#endif
B
bellard 已提交
5088 5089
}

5090
/* tlbwe */
5091
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
B
bellard 已提交
5092
{
5093
#if defined(CONFIG_USER_ONLY)
5094
    GEN_EXCP_PRIVOPC(ctx);
5095 5096
#else
    if (unlikely(!ctx->supervisor)) {
5097
        GEN_EXCP_PRIVOPC(ctx);
5098 5099 5100 5101
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
A
aurel32 已提交
5102 5103
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5104 5105 5106
        gen_op_4xx_tlbwe_hi();
        break;
    case 1:
A
aurel32 已提交
5107 5108
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5109 5110 5111
        gen_op_4xx_tlbwe_lo();
        break;
    default:
5112
        GEN_EXCP_INVAL(ctx);
5113
        break;
5114
    }
5115 5116 5117
#endif
}

5118
/* TLB management - PowerPC 440 implementation */
5119
/* tlbre */
5120
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5121 5122
{
#if defined(CONFIG_USER_ONLY)
5123
    GEN_EXCP_PRIVOPC(ctx);
5124 5125
#else
    if (unlikely(!ctx->supervisor)) {
5126
        GEN_EXCP_PRIVOPC(ctx);
5127 5128 5129 5130 5131 5132
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
A
aurel32 已提交
5133
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5134
        gen_op_440_tlbre(rB(ctx->opcode));
A
aurel32 已提交
5135
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5136 5137
        break;
    default:
5138
        GEN_EXCP_INVAL(ctx);
5139 5140 5141 5142 5143 5144
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
5145
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5146 5147
{
#if defined(CONFIG_USER_ONLY)
5148
    GEN_EXCP_PRIVOPC(ctx);
5149 5150
#else
    if (unlikely(!ctx->supervisor)) {
5151
        GEN_EXCP_PRIVOPC(ctx);
5152 5153 5154
        return;
    }
    gen_addr_reg_index(ctx);
5155
    gen_op_440_tlbsx();
5156
    if (Rc(ctx->opcode))
5157
        gen_op_4xx_tlbsx_check();
A
aurel32 已提交
5158
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5159 5160 5161 5162
#endif
}

/* tlbwe */
5163
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5164 5165
{
#if defined(CONFIG_USER_ONLY)
5166
    GEN_EXCP_PRIVOPC(ctx);
5167 5168
#else
    if (unlikely(!ctx->supervisor)) {
5169
        GEN_EXCP_PRIVOPC(ctx);
5170 5171 5172 5173 5174 5175
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
A
aurel32 已提交
5176 5177
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5178
        gen_op_440_tlbwe(rB(ctx->opcode));
5179 5180
        break;
    default:
5181
        GEN_EXCP_INVAL(ctx);
5182 5183 5184 5185 5186
        break;
    }
#endif
}

5187
/* wrtee */
5188
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
5189 5190
{
#if defined(CONFIG_USER_ONLY)
5191
    GEN_EXCP_PRIVOPC(ctx);
5192 5193
#else
    if (unlikely(!ctx->supervisor)) {
5194
        GEN_EXCP_PRIVOPC(ctx);
5195 5196
        return;
    }
A
aurel32 已提交
5197
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rD(ctx->opcode)]);
5198
    gen_op_wrte();
J
j_mayer 已提交
5199 5200 5201
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
5202
    GEN_STOP(ctx);
5203 5204 5205 5206
#endif
}

/* wrteei */
5207
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
5208 5209
{
#if defined(CONFIG_USER_ONLY)
5210
    GEN_EXCP_PRIVOPC(ctx);
5211 5212
#else
    if (unlikely(!ctx->supervisor)) {
5213
        GEN_EXCP_PRIVOPC(ctx);
5214 5215
        return;
    }
5216
    tcg_gen_movi_tl(cpu_T[0], ctx->opcode & 0x00010000);
5217
    gen_op_wrte();
J
j_mayer 已提交
5218 5219 5220
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
5221
    GEN_STOP(ctx);
5222 5223 5224
#endif
}

J
j_mayer 已提交
5225
/* PowerPC 440 specific instructions */
5226 5227 5228
/* dlmzb */
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
{
A
aurel32 已提交
5229 5230
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
5231
    gen_op_440_dlmzb();
A
aurel32 已提交
5232
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
5233 5234 5235
    gen_op_store_xer_bc();
    if (Rc(ctx->opcode)) {
        gen_op_440_dlmzb_update_Rc();
A
aurel32 已提交
5236
        tcg_gen_andi_i32(cpu_crf[0], cpu_T[0], 0xf);
5237 5238 5239 5240 5241 5242 5243 5244 5245 5246
    }
}

/* mbar replaces eieio on 440 */
GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
{
    /* interpreted as no-op */
}

/* msync replaces sync on 440 */
5247
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
5248 5249 5250 5251 5252
{
    /* interpreted as no-op */
}

/* icbt */
5253
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
5254 5255 5256 5257 5258
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
5259 5260
}

5261 5262 5263
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

5264 5265 5266 5267 5268 5269 5270 5271 5272
static always_inline void gen_load_avr(int t, int reg) {
    tcg_gen_mov_i64(cpu_AVRh[t], cpu_avrh[reg]);
    tcg_gen_mov_i64(cpu_AVRl[t], cpu_avrl[reg]);
}

static always_inline void gen_store_avr(int reg, int t) {
    tcg_gen_mov_i64(cpu_avrh[reg], cpu_AVRh[t]);
    tcg_gen_mov_i64(cpu_avrl[reg], cpu_AVRl[t]);
}
5273 5274 5275

#define op_vr_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_VR_LD_TABLE(name)                                                  \
5276 5277
static GenOpFunc *gen_op_vr_l##name[NB_MEM_FUNCS] = {                         \
    GEN_MEM_FUNCS(vr_l##name),                                                \
5278 5279
};
#define OP_VR_ST_TABLE(name)                                                  \
5280 5281
static GenOpFunc *gen_op_vr_st##name[NB_MEM_FUNCS] = {                        \
    GEN_MEM_FUNCS(vr_st##name),                                               \
5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292
};

#define GEN_VR_LDX(name, opc2, opc3)                                          \
GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)               \
{                                                                             \
    if (unlikely(!ctx->altivec_enabled)) {                                    \
        GEN_EXCP_NO_VR(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    gen_addr_reg_index(ctx);                                                  \
    op_vr_ldst(vr_l##name);                                                   \
5293
    gen_store_avr(rD(ctx->opcode), 0);                                        \
5294 5295 5296 5297 5298 5299 5300 5301 5302 5303
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)              \
{                                                                             \
    if (unlikely(!ctx->altivec_enabled)) {                                    \
        GEN_EXCP_NO_VR(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    gen_addr_reg_index(ctx);                                                  \
5304
    gen_load_avr(0, rS(ctx->opcode));                                         \
5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319
    op_vr_ldst(vr_st##name);                                                  \
}

OP_VR_LD_TABLE(vx);
GEN_VR_LDX(vx, 0x07, 0x03);
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
#define gen_op_vr_lvxl gen_op_vr_lvx
GEN_VR_LDX(vxl, 0x07, 0x0B);

OP_VR_ST_TABLE(vx);
GEN_VR_STX(vx, 0x07, 0x07);
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
#define gen_op_vr_stvxl gen_op_vr_stvx
GEN_VR_STX(vxl, 0x07, 0x0F);

5320 5321
/***                           SPE extension                               ***/
/* Register moves */
5322

A
aurel32 已提交
5323 5324 5325 5326 5327 5328 5329 5330 5331 5332
static always_inline void gen_load_gpr64(TCGv t, int reg) {
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
    tcg_gen_extu_i32_i64(t, cpu_gprh[reg]);
    tcg_gen_shli_i64(t, t, 32);
    TCGv tmp = tcg_temp_local_new(TCG_TYPE_I64);
    tcg_gen_extu_i32_i64(tmp, cpu_gpr[reg]);
    tcg_gen_or_i64(t, t, tmp);
    tcg_temp_free(tmp);
5333
#endif
A
aurel32 已提交
5334
}
5335

A
aurel32 已提交
5336 5337 5338 5339 5340 5341 5342 5343 5344
static always_inline void gen_store_gpr64(int reg, TCGv t) {
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
    tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
    TCGv tmp = tcg_temp_local_new(TCG_TYPE_I64);
    tcg_gen_shri_i64(tmp, t, 32);
    tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
    tcg_temp_free(tmp);
5345
#endif
A
aurel32 已提交
5346
}
5347

5348 5349 5350 5351 5352 5353 5354 5355 5356 5357
#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 */
5358
static always_inline void gen_speundef (DisasContext *ctx)
5359
{
5360
    GEN_EXCP_INVAL(ctx);
5361 5362 5363
}

/* SPE load and stores */
5364
static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
5365 5366 5367 5368
{
    target_long simm = rB(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
A
aurel32 已提交
5369
        tcg_gen_movi_tl(cpu_T[0], simm << sh);
5370
    } else {
A
aurel32 已提交
5371
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5372 5373 5374 5375 5376 5377 5378
        if (likely(simm != 0))
            gen_op_addi(simm << sh);
    }
}

#define op_spe_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_SPE_LD_TABLE(name)                                                 \
5379 5380
static GenOpFunc *gen_op_spe_l##name[NB_MEM_FUNCS] = {                        \
    GEN_MEM_FUNCS(spe_l##name),                                               \
5381 5382
};
#define OP_SPE_ST_TABLE(name)                                                 \
5383 5384
static GenOpFunc *gen_op_spe_st##name[NB_MEM_FUNCS] = {                       \
    GEN_MEM_FUNCS(spe_st##name),                                              \
5385
};
5386 5387

#define GEN_SPE_LD(name, sh)                                                  \
5388
static always_inline void gen_evl##name (DisasContext *ctx)                   \
5389 5390
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5391
        GEN_EXCP_NO_AP(ctx);                                                  \
5392 5393 5394 5395
        return;                                                               \
    }                                                                         \
    gen_addr_spe_imm_index(ctx, sh);                                          \
    op_spe_ldst(spe_l##name);                                                 \
A
aurel32 已提交
5396
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]);                             \
5397 5398 5399
}

#define GEN_SPE_LDX(name)                                                     \
5400
static always_inline void gen_evl##name##x (DisasContext *ctx)                \
5401 5402
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5403
        GEN_EXCP_NO_AP(ctx);                                                  \
5404 5405 5406 5407
        return;                                                               \
    }                                                                         \
    gen_addr_reg_index(ctx);                                                  \
    op_spe_ldst(spe_l##name);                                                 \
A
aurel32 已提交
5408
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]);                             \
5409 5410 5411 5412 5413 5414 5415 5416
}

#define GEN_SPEOP_LD(name, sh)                                                \
OP_SPE_LD_TABLE(name);                                                        \
GEN_SPE_LD(name, sh);                                                         \
GEN_SPE_LDX(name)

#define GEN_SPE_ST(name, sh)                                                  \
5417
static always_inline void gen_evst##name (DisasContext *ctx)                  \
5418 5419
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5420
        GEN_EXCP_NO_AP(ctx);                                                  \
5421 5422 5423
        return;                                                               \
    }                                                                         \
    gen_addr_spe_imm_index(ctx, sh);                                          \
A
aurel32 已提交
5424
    gen_load_gpr64(cpu_T64[1], rS(ctx->opcode));                              \
5425 5426 5427 5428
    op_spe_ldst(spe_st##name);                                                \
}

#define GEN_SPE_STX(name)                                                     \
5429
static always_inline void gen_evst##name##x (DisasContext *ctx)               \
5430 5431
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5432
        GEN_EXCP_NO_AP(ctx);                                                  \
5433 5434 5435
        return;                                                               \
    }                                                                         \
    gen_addr_reg_index(ctx);                                                  \
A
aurel32 已提交
5436
    gen_load_gpr64(cpu_T64[1], rS(ctx->opcode));                              \
5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450
    op_spe_ldst(spe_st##name);                                                \
}

#define GEN_SPEOP_ST(name, sh)                                                \
OP_SPE_ST_TABLE(name);                                                        \
GEN_SPE_ST(name, sh);                                                         \
GEN_SPE_STX(name)

#define GEN_SPEOP_LDST(name, sh)                                              \
GEN_SPEOP_LD(name, sh);                                                       \
GEN_SPEOP_ST(name, sh)

/* SPE arithmetic and logic */
#define GEN_SPEOP_ARITH2(name)                                                \
5451
static always_inline void gen_##name (DisasContext *ctx)                      \
5452 5453
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5454
        GEN_EXCP_NO_AP(ctx);                                                  \
5455 5456
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
5457 5458
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
5459
    gen_op_##name();                                                          \
A
aurel32 已提交
5460
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
5461 5462 5463
}

#define GEN_SPEOP_ARITH1(name)                                                \
5464
static always_inline void gen_##name (DisasContext *ctx)                      \
5465 5466
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5467
        GEN_EXCP_NO_AP(ctx);                                                  \
5468 5469
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
5470
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
5471
    gen_op_##name();                                                          \
A
aurel32 已提交
5472
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
5473 5474 5475
}

#define GEN_SPEOP_COMP(name)                                                  \
5476
static always_inline void gen_##name (DisasContext *ctx)                      \
5477 5478
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5479
        GEN_EXCP_NO_AP(ctx);                                                  \
5480 5481
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
5482 5483
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
5484
    gen_op_##name();                                                          \
A
aurel32 已提交
5485
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);              \
5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515
}

/* Logical */
GEN_SPEOP_ARITH2(evand);
GEN_SPEOP_ARITH2(evandc);
GEN_SPEOP_ARITH2(evxor);
GEN_SPEOP_ARITH2(evor);
GEN_SPEOP_ARITH2(evnor);
GEN_SPEOP_ARITH2(eveqv);
GEN_SPEOP_ARITH2(evorc);
GEN_SPEOP_ARITH2(evnand);
GEN_SPEOP_ARITH2(evsrwu);
GEN_SPEOP_ARITH2(evsrws);
GEN_SPEOP_ARITH2(evslw);
GEN_SPEOP_ARITH2(evrlw);
GEN_SPEOP_ARITH2(evmergehi);
GEN_SPEOP_ARITH2(evmergelo);
GEN_SPEOP_ARITH2(evmergehilo);
GEN_SPEOP_ARITH2(evmergelohi);

/* Arithmetic */
GEN_SPEOP_ARITH2(evaddw);
GEN_SPEOP_ARITH2(evsubfw);
GEN_SPEOP_ARITH1(evabs);
GEN_SPEOP_ARITH1(evneg);
GEN_SPEOP_ARITH1(evextsb);
GEN_SPEOP_ARITH1(evextsh);
GEN_SPEOP_ARITH1(evrndw);
GEN_SPEOP_ARITH1(evcntlzw);
GEN_SPEOP_ARITH1(evcntlsw);
5516
static always_inline void gen_brinc (DisasContext *ctx)
5517 5518
{
    /* Note: brinc is usable even if SPE is disabled */
A
aurel32 已提交
5519 5520
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
5521
    gen_op_brinc();
A
aurel32 已提交
5522
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5523 5524 5525
}

#define GEN_SPEOP_ARITH_IMM2(name)                                            \
5526
static always_inline void gen_##name##i (DisasContext *ctx)                   \
5527 5528
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5529
        GEN_EXCP_NO_AP(ctx);                                                  \
5530 5531
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
5532
    gen_load_gpr64(cpu_T64[0], rB(ctx->opcode));                              \
5533 5534
    gen_op_splatwi_T1_64(rA(ctx->opcode));                                    \
    gen_op_##name();                                                          \
A
aurel32 已提交
5535
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
5536 5537 5538
}

#define GEN_SPEOP_LOGIC_IMM2(name)                                            \
5539
static always_inline void gen_##name##i (DisasContext *ctx)                   \
5540 5541
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5542
        GEN_EXCP_NO_AP(ctx);                                                  \
5543 5544
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
5545
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
5546 5547
    gen_op_splatwi_T1_64(rB(ctx->opcode));                                    \
    gen_op_##name();                                                          \
A
aurel32 已提交
5548
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561
}

GEN_SPEOP_ARITH_IMM2(evaddw);
#define gen_evaddiw gen_evaddwi
GEN_SPEOP_ARITH_IMM2(evsubfw);
#define gen_evsubifw gen_evsubfwi
GEN_SPEOP_LOGIC_IMM2(evslw);
GEN_SPEOP_LOGIC_IMM2(evsrwu);
#define gen_evsrwis gen_evsrwsi
GEN_SPEOP_LOGIC_IMM2(evsrws);
#define gen_evsrwiu gen_evsrwui
GEN_SPEOP_LOGIC_IMM2(evrlw);

5562
static always_inline void gen_evsplati (DisasContext *ctx)
5563 5564 5565 5566
{
    int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;

    gen_op_splatwi_T0_64(imm);
A
aurel32 已提交
5567
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
5568 5569
}

5570
static always_inline void gen_evsplatfi (DisasContext *ctx)
5571 5572 5573 5574
{
    uint32_t imm = rA(ctx->opcode) << 27;

    gen_op_splatwi_T0_64(imm);
A
aurel32 已提交
5575
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610
}

/* Comparison */
GEN_SPEOP_COMP(evcmpgtu);
GEN_SPEOP_COMP(evcmpgts);
GEN_SPEOP_COMP(evcmpltu);
GEN_SPEOP_COMP(evcmplts);
GEN_SPEOP_COMP(evcmpeq);

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); ////

5611
static always_inline void gen_evsel (DisasContext *ctx)
5612 5613
{
    if (unlikely(!ctx->spe_enabled)) {
5614
        GEN_EXCP_NO_AP(ctx);
5615 5616
        return;
    }
A
aurel32 已提交
5617
    tcg_gen_mov_i32(cpu_T[0], cpu_crf[ctx->opcode & 0x7]);
A
aurel32 已提交
5618 5619
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));
5620
    gen_op_evsel();
A
aurel32 已提交
5621
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
5622 5623
}

5624
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
5625 5626 5627
{
    gen_evsel(ctx);
}
5628
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
5629 5630 5631
{
    gen_evsel(ctx);
}
5632
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
5633 5634 5635
{
    gen_evsel(ctx);
}
5636
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
5637 5638 5639 5640 5641 5642 5643 5644 5645
{
    gen_evsel(ctx);
}

/* Load and stores */
#if defined(TARGET_PPC64)
/* In that case, we already have 64 bits load & stores
 * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
 */
5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677
#define gen_op_spe_ldd_raw           gen_op_ld_raw
#define gen_op_spe_ldd_user          gen_op_ld_user
#define gen_op_spe_ldd_kernel        gen_op_ld_kernel
#define gen_op_spe_ldd_hypv          gen_op_ld_hypv
#define gen_op_spe_ldd_64_raw        gen_op_ld_64_raw
#define gen_op_spe_ldd_64_user       gen_op_ld_64_user
#define gen_op_spe_ldd_64_kernel     gen_op_ld_64_kernel
#define gen_op_spe_ldd_64_hypv       gen_op_ld_64_hypv
#define gen_op_spe_ldd_le_raw        gen_op_ld_le_raw
#define gen_op_spe_ldd_le_user       gen_op_ld_le_user
#define gen_op_spe_ldd_le_kernel     gen_op_ld_le_kernel
#define gen_op_spe_ldd_le_hypv       gen_op_ld_le_hypv
#define gen_op_spe_ldd_le_64_raw     gen_op_ld_le_64_raw
#define gen_op_spe_ldd_le_64_user    gen_op_ld_le_64_user
#define gen_op_spe_ldd_le_64_kernel  gen_op_ld_le_64_kernel
#define gen_op_spe_ldd_le_64_hypv    gen_op_ld_le_64_hypv
#define gen_op_spe_stdd_raw          gen_op_std_raw
#define gen_op_spe_stdd_user         gen_op_std_user
#define gen_op_spe_stdd_kernel       gen_op_std_kernel
#define gen_op_spe_stdd_hypv         gen_op_std_hypv
#define gen_op_spe_stdd_64_raw       gen_op_std_64_raw
#define gen_op_spe_stdd_64_user      gen_op_std_64_user
#define gen_op_spe_stdd_64_kernel    gen_op_std_64_kernel
#define gen_op_spe_stdd_64_hypv      gen_op_std_64_hypv
#define gen_op_spe_stdd_le_raw       gen_op_std_le_raw
#define gen_op_spe_stdd_le_user      gen_op_std_le_user
#define gen_op_spe_stdd_le_kernel    gen_op_std_le_kernel
#define gen_op_spe_stdd_le_hypv      gen_op_std_le_hypv
#define gen_op_spe_stdd_le_64_raw    gen_op_std_le_64_raw
#define gen_op_spe_stdd_le_64_user   gen_op_std_le_64_user
#define gen_op_spe_stdd_le_64_kernel gen_op_std_le_64_kernel
#define gen_op_spe_stdd_le_64_hypv   gen_op_std_le_64_hypv
5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688
#endif /* defined(TARGET_PPC64) */
GEN_SPEOP_LDST(dd, 3);
GEN_SPEOP_LDST(dw, 3);
GEN_SPEOP_LDST(dh, 3);
GEN_SPEOP_LDST(whe, 2);
GEN_SPEOP_LD(whou, 2);
GEN_SPEOP_LD(whos, 2);
GEN_SPEOP_ST(who, 2);

#if defined(TARGET_PPC64)
/* In that case, spe_stwwo is equivalent to stw */
5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702
#define gen_op_spe_stwwo_raw          gen_op_stw_raw
#define gen_op_spe_stwwo_user         gen_op_stw_user
#define gen_op_spe_stwwo_kernel       gen_op_stw_kernel
#define gen_op_spe_stwwo_hypv         gen_op_stw_hypv
#define gen_op_spe_stwwo_le_raw       gen_op_stw_le_raw
#define gen_op_spe_stwwo_le_user      gen_op_stw_le_user
#define gen_op_spe_stwwo_le_kernel    gen_op_stw_le_kernel
#define gen_op_spe_stwwo_le_hypv      gen_op_stw_le_hypv
#define gen_op_spe_stwwo_64_raw       gen_op_stw_64_raw
#define gen_op_spe_stwwo_64_user      gen_op_stw_64_user
#define gen_op_spe_stwwo_64_kernel    gen_op_stw_64_kernel
#define gen_op_spe_stwwo_64_hypv      gen_op_stw_64_hypv
#define gen_op_spe_stwwo_le_64_raw    gen_op_stw_le_64_raw
#define gen_op_spe_stwwo_le_64_user   gen_op_stw_le_64_user
5703
#define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
5704
#define gen_op_spe_stwwo_le_64_hypv   gen_op_stw_le_64_hypv
5705 5706
#endif
#define _GEN_OP_SPE_STWWE(suffix)                                             \
5707
static always_inline void gen_op_spe_stwwe_##suffix (void)                    \
5708 5709 5710 5711 5712
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_##suffix();                                              \
}
#define _GEN_OP_SPE_STWWE_LE(suffix)                                          \
5713
static always_inline void gen_op_spe_stwwe_le_##suffix (void)                 \
5714 5715 5716 5717 5718 5719 5720 5721
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_le_##suffix();                                           \
}
#if defined(TARGET_PPC64)
#define GEN_OP_SPE_STWWE(suffix)                                              \
_GEN_OP_SPE_STWWE(suffix);                                                    \
_GEN_OP_SPE_STWWE_LE(suffix);                                                 \
5722
static always_inline void gen_op_spe_stwwe_64_##suffix (void)                 \
5723 5724 5725 5726
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_64_##suffix();                                           \
}                                                                             \
5727
static always_inline void gen_op_spe_stwwe_le_64_##suffix (void)              \
5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_le_64_##suffix();                                        \
}
#else
#define GEN_OP_SPE_STWWE(suffix)                                              \
_GEN_OP_SPE_STWWE(suffix);                                                    \
_GEN_OP_SPE_STWWE_LE(suffix)
#endif
#if defined(CONFIG_USER_ONLY)
GEN_OP_SPE_STWWE(raw);
#else /* defined(CONFIG_USER_ONLY) */
GEN_OP_SPE_STWWE(user);
5741 5742
GEN_OP_SPE_STWWE(kernel);
GEN_OP_SPE_STWWE(hypv);
5743 5744 5745 5746 5747
#endif /* defined(CONFIG_USER_ONLY) */
GEN_SPEOP_ST(wwe, 2);
GEN_SPEOP_ST(wwo, 2);

#define GEN_SPE_LDSPLAT(name, op, suffix)                                     \
5748
static always_inline void gen_op_spe_l##name##_##suffix (void)                \
5749 5750 5751 5752 5753 5754
{                                                                             \
    gen_op_##op##_##suffix();                                                 \
    gen_op_splatw_T1_64();                                                    \
}

#define GEN_OP_SPE_LHE(suffix)                                                \
5755
static always_inline void gen_op_spe_lhe_##suffix (void)                      \
5756 5757 5758 5759 5760 5761
{                                                                             \
    gen_op_spe_lh_##suffix();                                                 \
    gen_op_sli16_T1_64();                                                     \
}

#define GEN_OP_SPE_LHX(suffix)                                                \
5762
static always_inline void gen_op_spe_lhx_##suffix (void)                      \
5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792
{                                                                             \
    gen_op_spe_lh_##suffix();                                                 \
    gen_op_extsh_T1_64();                                                     \
}

#if defined(CONFIG_USER_ONLY)
GEN_OP_SPE_LHE(raw);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
GEN_OP_SPE_LHE(le_raw);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
GEN_OP_SPE_LHX(raw);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
GEN_OP_SPE_LHX(le_raw);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
#if defined(TARGET_PPC64)
GEN_OP_SPE_LHE(64_raw);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
GEN_OP_SPE_LHE(le_64_raw);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
GEN_OP_SPE_LHX(64_raw);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
GEN_OP_SPE_LHX(le_64_raw);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
#endif
#else
GEN_OP_SPE_LHE(user);
5793 5794
GEN_OP_SPE_LHE(kernel);
GEN_OP_SPE_LHE(hypv);
5795
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
5796 5797
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, hypv);
5798
GEN_OP_SPE_LHE(le_user);
5799 5800
GEN_OP_SPE_LHE(le_kernel);
GEN_OP_SPE_LHE(le_hypv);
5801
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
5802 5803
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_hypv);
5804
GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
5805 5806
GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, hypv);
5807
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
5808 5809
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_hypv);
5810
GEN_OP_SPE_LHX(user);
5811 5812
GEN_OP_SPE_LHX(kernel);
GEN_OP_SPE_LHX(hypv);
5813
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
5814 5815
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, hypv);
5816
GEN_OP_SPE_LHX(le_user);
5817 5818
GEN_OP_SPE_LHX(le_kernel);
GEN_OP_SPE_LHX(le_hypv);
5819
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
5820 5821
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_hypv);
5822 5823
#if defined(TARGET_PPC64)
GEN_OP_SPE_LHE(64_user);
5824 5825
GEN_OP_SPE_LHE(64_kernel);
GEN_OP_SPE_LHE(64_hypv);
5826
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
5827 5828
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_hypv);
5829
GEN_OP_SPE_LHE(le_64_user);
5830 5831
GEN_OP_SPE_LHE(le_64_kernel);
GEN_OP_SPE_LHE(le_64_hypv);
5832
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
5833 5834
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_hypv);
5835
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
5836 5837
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_hypv);
5838
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
5839 5840
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_hypv);
5841
GEN_OP_SPE_LHX(64_user);
5842 5843
GEN_OP_SPE_LHX(64_kernel);
GEN_OP_SPE_LHX(64_hypv);
5844
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
5845 5846
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_hypv);
5847
GEN_OP_SPE_LHX(le_64_user);
5848 5849
GEN_OP_SPE_LHX(le_64_kernel);
GEN_OP_SPE_LHX(le_64_hypv);
5850
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
5851 5852
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_hypv);
5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957
#endif
#endif
GEN_SPEOP_LD(hhesplat, 1);
GEN_SPEOP_LD(hhousplat, 1);
GEN_SPEOP_LD(hhossplat, 1);
GEN_SPEOP_LD(wwsplat, 2);
GEN_SPEOP_LD(whsplat, 2);

GEN_SPE(evlddx,         evldd,         0x00, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evldwx,         evldw,         0x01, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evldhx,         evldh,         0x02, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlhhesplatx,   evlhhesplat,   0x04, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlhhousplatx,  evlhhousplat,  0x06, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlhhossplatx,  evlhhossplat,  0x07, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwhex,        evlwhe,        0x08, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwhoux,       evlwhou,       0x0A, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwhosx,       evlwhos,       0x0B, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwwsplatx,    evlwwsplat,    0x0C, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evlwhsplatx,    evlwhsplat,    0x0E, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstddx,        evstdd,        0x10, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstdwx,        evstdw,        0x11, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstdhx,        evstdh,        0x12, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstwhex,       evstwhe,       0x18, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstwhox,       evstwho,       0x1A, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstwwex,       evstwwe,       0x1C, 0x0C, 0x00000000, PPC_SPE); //
GEN_SPE(evstwwox,       evstwwo,       0x1E, 0x0C, 0x00000000, PPC_SPE); //

/* 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                     ***/
#define GEN_SPEFPUOP_CONV(name)                                               \
5958
static always_inline void gen_##name (DisasContext *ctx)                      \
5959
{                                                                             \
A
aurel32 已提交
5960
    gen_load_gpr64(cpu_T64[0], rB(ctx->opcode));                              \
5961
    gen_op_##name();                                                          \
A
aurel32 已提交
5962
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038
}

/* Single precision floating-point vectors operations */
/* Arithmetic */
GEN_SPEOP_ARITH2(evfsadd);
GEN_SPEOP_ARITH2(evfssub);
GEN_SPEOP_ARITH2(evfsmul);
GEN_SPEOP_ARITH2(evfsdiv);
GEN_SPEOP_ARITH1(evfsabs);
GEN_SPEOP_ARITH1(evfsnabs);
GEN_SPEOP_ARITH1(evfsneg);
/* Conversion */
GEN_SPEFPUOP_CONV(evfscfui);
GEN_SPEFPUOP_CONV(evfscfsi);
GEN_SPEFPUOP_CONV(evfscfuf);
GEN_SPEFPUOP_CONV(evfscfsf);
GEN_SPEFPUOP_CONV(evfsctui);
GEN_SPEFPUOP_CONV(evfsctsi);
GEN_SPEFPUOP_CONV(evfsctuf);
GEN_SPEFPUOP_CONV(evfsctsf);
GEN_SPEFPUOP_CONV(evfsctuiz);
GEN_SPEFPUOP_CONV(evfsctsiz);
/* Comparison */
GEN_SPEOP_COMP(evfscmpgt);
GEN_SPEOP_COMP(evfscmplt);
GEN_SPEOP_COMP(evfscmpeq);
GEN_SPEOP_COMP(evfststgt);
GEN_SPEOP_COMP(evfststlt);
GEN_SPEOP_COMP(evfststeq);

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

/* Single precision floating-point operations */
/* Arithmetic */
GEN_SPEOP_ARITH2(efsadd);
GEN_SPEOP_ARITH2(efssub);
GEN_SPEOP_ARITH2(efsmul);
GEN_SPEOP_ARITH2(efsdiv);
GEN_SPEOP_ARITH1(efsabs);
GEN_SPEOP_ARITH1(efsnabs);
GEN_SPEOP_ARITH1(efsneg);
/* Conversion */
GEN_SPEFPUOP_CONV(efscfui);
GEN_SPEFPUOP_CONV(efscfsi);
GEN_SPEFPUOP_CONV(efscfuf);
GEN_SPEFPUOP_CONV(efscfsf);
GEN_SPEFPUOP_CONV(efsctui);
GEN_SPEFPUOP_CONV(efsctsi);
GEN_SPEFPUOP_CONV(efsctuf);
GEN_SPEFPUOP_CONV(efsctsf);
GEN_SPEFPUOP_CONV(efsctuiz);
GEN_SPEFPUOP_CONV(efsctsiz);
GEN_SPEFPUOP_CONV(efscfd);
/* Comparison */
GEN_SPEOP_COMP(efscmpgt);
GEN_SPEOP_COMP(efscmplt);
GEN_SPEOP_COMP(efscmpeq);
GEN_SPEOP_COMP(efststgt);
GEN_SPEOP_COMP(efststlt);
GEN_SPEOP_COMP(efststeq);

/* Opcodes definitions */
6039
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
6040 6041 6042 6043 6044 6045 6046 6047 6048
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
6049 6050
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //

/* Double precision floating-point operations */
/* Arithmetic */
GEN_SPEOP_ARITH2(efdadd);
GEN_SPEOP_ARITH2(efdsub);
GEN_SPEOP_ARITH2(efdmul);
GEN_SPEOP_ARITH2(efddiv);
GEN_SPEOP_ARITH1(efdabs);
GEN_SPEOP_ARITH1(efdnabs);
GEN_SPEOP_ARITH1(efdneg);
/* Conversion */

GEN_SPEFPUOP_CONV(efdcfui);
GEN_SPEFPUOP_CONV(efdcfsi);
GEN_SPEFPUOP_CONV(efdcfuf);
GEN_SPEFPUOP_CONV(efdcfsf);
GEN_SPEFPUOP_CONV(efdctui);
GEN_SPEFPUOP_CONV(efdctsi);
GEN_SPEFPUOP_CONV(efdctuf);
GEN_SPEFPUOP_CONV(efdctsf);
GEN_SPEFPUOP_CONV(efdctuiz);
GEN_SPEFPUOP_CONV(efdctsiz);
GEN_SPEFPUOP_CONV(efdcfs);
GEN_SPEFPUOP_CONV(efdcfuid);
GEN_SPEFPUOP_CONV(efdcfsid);
GEN_SPEFPUOP_CONV(efdctuidz);
GEN_SPEFPUOP_CONV(efdctsidz);
/* Comparison */
GEN_SPEOP_COMP(efdcmpgt);
GEN_SPEOP_COMP(efdcmplt);
GEN_SPEOP_COMP(efdcmpeq);
GEN_SPEOP_COMP(efdtstgt);
GEN_SPEOP_COMP(efdtstlt);
GEN_SPEOP_COMP(efdtsteq);

/* Opcodes definitions */
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //

B
bellard 已提交
6106 6107 6108
/* End opcode list */
GEN_OPCODE_MARK(end);

6109
#include "translate_init.c"
6110
#include "helper_regs.h"
B
bellard 已提交
6111

6112
/*****************************************************************************/
6113
/* Misc PowerPC helpers */
6114 6115 6116
void cpu_dump_state (CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
B
bellard 已提交
6117
{
6118 6119 6120
#define RGPL  4
#define RFPL  4

B
bellard 已提交
6121 6122
    int i;

J
j_mayer 已提交
6123 6124
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
                env->nip, env->lr, env->ctr, hreg_load_xer(env));
6125 6126
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
6127
#if !defined(NO_TIMER_DUMP)
J
j_mayer 已提交
6128
    cpu_fprintf(f, "TB %08x %08x "
6129 6130 6131 6132
#if !defined(CONFIG_USER_ONLY)
                "DECR %08x"
#endif
                "\n",
J
j_mayer 已提交
6133
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
6134 6135 6136 6137
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
6138
#endif
6139
    for (i = 0; i < 32; i++) {
6140 6141
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
6142
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
6143
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
6144
            cpu_fprintf(f, "\n");
6145
    }
6146
    cpu_fprintf(f, "CR ");
6147
    for (i = 0; i < 8; i++)
B
bellard 已提交
6148 6149
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
6150 6151 6152 6153 6154 6155 6156 6157
    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 已提交
6158
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
6159
    }
6160
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
6161 6162 6163
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
6164
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
6165
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
6166
            cpu_fprintf(f, "\n");
B
bellard 已提交
6167
    }
6168
#if !defined(CONFIG_USER_ONLY)
6169
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
6170
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
6171
#endif
B
bellard 已提交
6172

6173 6174
#undef RGPL
#undef RFPL
B
bellard 已提交
6175 6176
}

6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 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
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
}

6224
/*****************************************************************************/
6225 6226 6227
static always_inline void gen_intermediate_code_internal (CPUState *env,
                                                          TranslationBlock *tb,
                                                          int search_pc)
B
bellard 已提交
6228
{
6229
    DisasContext ctx, *ctxp = &ctx;
B
bellard 已提交
6230
    opc_handler_t **table, *handler;
B
bellard 已提交
6231
    target_ulong pc_start;
B
bellard 已提交
6232
    uint16_t *gen_opc_end;
6233
    int supervisor, little_endian;
B
bellard 已提交
6234
    int j, lj = -1;
P
pbrook 已提交
6235 6236
    int num_insns;
    int max_insns;
B
bellard 已提交
6237 6238 6239

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6240 6241 6242
#if defined(OPTIMIZE_FPRF_UPDATE)
    gen_fprf_ptr = gen_fprf_buf;
#endif
B
bellard 已提交
6243
    ctx.nip = pc_start;
B
bellard 已提交
6244
    ctx.tb = tb;
6245
    ctx.exception = POWERPC_EXCP_NONE;
6246
    ctx.spr_cb = env->spr_cb;
6247 6248
    supervisor = env->mmu_idx;
#if !defined(CONFIG_USER_ONLY)
6249
    ctx.supervisor = supervisor;
6250
#endif
6251
    little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
6252 6253
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
6254
    ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
6255
#else
6256
    ctx.mem_idx = (supervisor << 1) | little_endian;
6257
#endif
6258
    ctx.dcache_line_size = env->dcache_line_size;
B
bellard 已提交
6259
    ctx.fpu_enabled = msr_fp;
6260
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
6261 6262 6263
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
6264 6265 6266 6267
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
6268
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
6269
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
6270
    else
6271
        ctx.singlestep_enabled = 0;
6272
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
6273 6274 6275
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
6276
#if defined (DO_SINGLE_STEP) && 0
6277 6278 6279
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
6280 6281 6282 6283 6284 6285
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
6286
    /* Set env in case of segfault during code fetch */
6287
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
6288 6289
        if (unlikely(env->nb_breakpoints > 0)) {
            for (j = 0; j < env->nb_breakpoints; j++) {
6290
                if (env->breakpoints[j] == ctx.nip) {
6291
                    gen_update_nip(&ctx, ctx.nip);
6292 6293 6294 6295 6296
                    gen_op_debug();
                    break;
                }
            }
        }
6297
        if (unlikely(search_pc)) {
B
bellard 已提交
6298 6299 6300 6301 6302
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
6303
                gen_opc_pc[lj] = ctx.nip;
B
bellard 已提交
6304
                gen_opc_instr_start[lj] = 1;
P
pbrook 已提交
6305
                gen_opc_icount[lj] = num_insns;
B
bellard 已提交
6306 6307
            }
        }
6308 6309
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
B
bellard 已提交
6310
            fprintf(logfile, "----------------\n");
6311
            fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
6312
                    ctx.nip, supervisor, (int)msr_ir);
6313 6314
        }
#endif
P
pbrook 已提交
6315 6316
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
6317 6318 6319 6320
        if (unlikely(little_endian)) {
            ctx.opcode = bswap32(ldl_code(ctx.nip));
        } else {
            ctx.opcode = ldl_code(ctx.nip);
6321
        }
6322 6323
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
6324
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6325
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
6326
                    opc3(ctx.opcode), little_endian ? "little" : "big");
B
bellard 已提交
6327 6328
        }
#endif
B
bellard 已提交
6329
        ctx.nip += 4;
6330
        table = env->opcodes;
P
pbrook 已提交
6331
        num_insns++;
B
bellard 已提交
6332 6333 6334 6335 6336 6337 6338 6339 6340 6341
        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 ? */
6342
        if (unlikely(handler->handler == &gen_invalid)) {
J
j_mayer 已提交
6343
            if (loglevel != 0) {
6344
                fprintf(logfile, "invalid/unsupported opcode: "
6345
                        "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
6346
                        opc1(ctx.opcode), opc2(ctx.opcode),
6347
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
6348 6349
            } else {
                printf("invalid/unsupported opcode: "
6350
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
B
bellard 已提交
6351
                       opc1(ctx.opcode), opc2(ctx.opcode),
6352
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
6353
            }
6354 6355
        } else {
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
J
j_mayer 已提交
6356
                if (loglevel != 0) {
B
bellard 已提交
6357
                    fprintf(logfile, "invalid bits: %08x for opcode: "
6358
                            "%02x - %02x - %02x (%08x) " ADDRX "\n",
B
bellard 已提交
6359 6360
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
                            opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
6361
                            ctx.opcode, ctx.nip - 4);
6362 6363
                } else {
                    printf("invalid bits: %08x for opcode: "
6364
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
6365 6366
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
                           opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
6367
                           ctx.opcode, ctx.nip - 4);
6368
                }
6369
                GEN_EXCP_INVAL(ctxp);
B
bellard 已提交
6370
                break;
B
bellard 已提交
6371 6372
            }
        }
B
bellard 已提交
6373
        (*(handler->handler))(&ctx);
6374 6375 6376
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
6377
        /* Check trace mode exceptions */
6378 6379 6380 6381 6382
        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)) {
6383
            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
6384
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
6385 6386
                            (env->singlestep_enabled) ||
                            num_insns >= max_insns)) {
6387 6388 6389
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
6390
            break;
6391
        }
6392 6393 6394 6395
#if defined (DO_SINGLE_STEP)
        break;
#endif
    }
P
pbrook 已提交
6396 6397
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
6398
    if (ctx.exception == POWERPC_EXCP_NONE) {
6399
        gen_goto_tb(&ctx, 0, ctx.nip);
6400
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
6401 6402 6403 6404
        if (unlikely(env->singlestep_enabled)) {
            gen_update_nip(&ctx, ctx.nip);
            gen_op_debug();
        }
6405
        /* Generate the return instruction */
B
bellard 已提交
6406
        tcg_gen_exit_tb(0);
6407
    }
P
pbrook 已提交
6408
    gen_icount_end(tb, num_insns);
B
bellard 已提交
6409
    *gen_opc_ptr = INDEX_op_end;
6410
    if (unlikely(search_pc)) {
6411 6412 6413 6414 6415
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
B
bellard 已提交
6416
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
6417
        tb->icount = num_insns;
6418
    }
6419
#if defined(DEBUG_DISAS)
6420
    if (loglevel & CPU_LOG_TB_CPU) {
6421
        fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
B
bellard 已提交
6422
        cpu_dump_state(env, logfile, fprintf, 0);
6423 6424
    }
    if (loglevel & CPU_LOG_TB_IN_ASM) {
6425
        int flags;
6426
        flags = env->bfd_mach;
6427
        flags |= little_endian << 16;
B
bellard 已提交
6428
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6429
        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
B
bellard 已提交
6430
        fprintf(logfile, "\n");
6431
    }
B
bellard 已提交
6432 6433 6434
#endif
}

6435
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
6436
{
6437
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
6438 6439
}

6440
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
6441
{
6442
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
6443
}
A
aurel32 已提交
6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485

void gen_pc_load(CPUState *env, TranslationBlock *tb,
                unsigned long searched_pc, int pc_pos, void *puc)
{
    int type, c;
    /* for PPC, we need to look at the micro operation to get the
     * access type */
    env->nip = gen_opc_pc[pc_pos];
    c = gen_opc_buf[pc_pos];
    switch(c) {
#if defined(CONFIG_USER_ONLY)
#define CASE3(op)\
    case INDEX_op_ ## op ## _raw
#else
#define CASE3(op)\
    case INDEX_op_ ## op ## _user:\
    case INDEX_op_ ## op ## _kernel:\
    case INDEX_op_ ## op ## _hypv
#endif

    CASE3(stfd):
    CASE3(stfs):
    CASE3(lfd):
    CASE3(lfs):
        type = ACCESS_FLOAT;
        break;
    CASE3(lwarx):
        type = ACCESS_RES;
        break;
    CASE3(stwcx):
        type = ACCESS_RES;
        break;
    CASE3(eciwx):
    CASE3(ecowx):
        type = ACCESS_EXT;
        break;
    default:
        type = ACCESS_INT;
        break;
    }
    env->access_type = type;
}