translate.c 248.4 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 DO_PPC_STATISTICS
41
//#define OPTIMIZE_FPRF_UPDATE
B
bellard 已提交
42

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

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

/* 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 已提交
75
static TCGv cpu_FT[3];
76
static TCGv cpu_AVRh[3], cpu_AVRl[3];
P
pbrook 已提交
77 78 79 80 81

#include "gen-icount.h"

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

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

P
pbrook 已提交
89
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
A
aurel32 已提交
90 91 92 93 94 95 96 97 98 99
#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");
100 101 102 103 104 105 106 107
#ifdef HOST_I386
    /* XXX: This is a temporary workaround for i386.
     *      On i386 qemu_st32 runs out of registers.
     *      The proper fix is to remove cpu_T.
     */
    cpu_T[2] = tcg_global_mem_new(TCG_TYPE_TL,
                                  TCG_AREG0, offsetof(CPUState, t2), "T2");
#else
A
aurel32 已提交
108 109
    cpu_T[2] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T2");
#endif
110
#endif
A
aurel32 已提交
111 112
#if !defined(TARGET_PPC64)
    cpu_T64[0] = tcg_global_mem_new(TCG_TYPE_I64,
A
aurel32 已提交
113
                                    TCG_AREG0, offsetof(CPUState, t0_64),
A
aurel32 已提交
114 115
                                    "T0_64");
    cpu_T64[1] = tcg_global_mem_new(TCG_TYPE_I64,
A
aurel32 已提交
116
                                    TCG_AREG0, offsetof(CPUState, t1_64),
A
aurel32 已提交
117 118
                                    "T1_64");
    cpu_T64[2] = tcg_global_mem_new(TCG_TYPE_I64,
A
aurel32 已提交
119
                                    TCG_AREG0, offsetof(CPUState, t2_64),
A
aurel32 已提交
120 121
                                    "T2_64");
#endif
A
aurel32 已提交
122 123 124 125 126 127 128 129

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

130 131 132 133 134 135 136 137 138 139 140 141 142
    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 已提交
143
    p = cpu_reg_names;
A
aurel32 已提交
144 145 146 147 148 149 150 151

    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 已提交
152 153 154 155 156 157 158 159 160 161 162
    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
163

A
aurel32 已提交
164 165 166
        sprintf(p, "fp%d", i);
        cpu_fpr[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                        offsetof(CPUState, fpr[i]), p);
A
aurel32 已提交
167
        p += (i < 10) ? 4 : 5;
A
aurel32 已提交
168

169 170 171 172
        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 已提交
173

174 175 176 177
        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 已提交
178
    }
A
aurel32 已提交
179

A
aurel32 已提交
180 181 182
    cpu_nip = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
                                 offsetof(CPUState, nip), "nip");

A
aurel32 已提交
183 184 185 186 187 188
    cpu_ctr = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
                                 offsetof(CPUState, ctr), "ctr");

    cpu_lr = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
                                offsetof(CPUState, lr), "lr");

A
aurel32 已提交
189 190 191
    cpu_xer = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
                                 offsetof(CPUState, xer), "xer");

192 193 194
    cpu_fpscr = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
                                   offsetof(CPUState, fpscr), "fpscr");

A
aurel32 已提交
195 196 197 198 199
    /* register helpers */
#undef DEF_HELPER
#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
#include "helper.h"

P
pbrook 已提交
200 201 202
    done_init = 1;
}

203 204 205 206
#if defined(OPTIMIZE_FPRF_UPDATE)
static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
static uint16_t **gen_fprf_ptr;
#endif
B
bellard 已提交
207 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 char *oname;
240 241
#endif
#if defined(DO_PPC_STATISTICS)
242 243
    uint64_t count;
#endif
244
};
B
bellard 已提交
245

246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
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 已提交
262
            tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
263 264 265 266
        gen_op_float_check_status();
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
        gen_op_compute_fprf(0);
A
aurel32 已提交
267
        tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
        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
}

284
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
285 286 287
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
A
aurel32 已提交
288
        tcg_gen_movi_tl(cpu_nip, nip);
289 290
    else
#endif
A
aurel32 已提交
291
        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
292 293
}

294
#define GEN_EXCP(ctx, excp, error)                                            \
B
bellard 已提交
295
do {                                                                          \
296
    if ((ctx)->exception == POWERPC_EXCP_NONE) {                              \
297
        gen_update_nip(ctx, (ctx)->nip);                                      \
298 299 300
    }                                                                         \
    gen_op_raise_exception_err((excp), (error));                              \
    ctx->exception = (excp);                                                  \
B
bellard 已提交
301 302
} while (0)

303 304 305
#define GEN_EXCP_INVAL(ctx)                                                   \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
306

307 308 309
#define GEN_EXCP_PRIVOPC(ctx)                                                 \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
310

311 312 313 314 315 316 317 318 319
#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)
320

321 322 323
#define GEN_EXCP_NO_VR(ctx)                                                   \
GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)

324
/* Stop translation */
325
static always_inline void GEN_STOP (DisasContext *ctx)
326
{
327
    gen_update_nip(ctx, ctx->nip);
328
    ctx->exception = POWERPC_EXCP_STOP;
329 330
}

331
/* No need to update nip here, as execution flow will change */
332
static always_inline void GEN_SYNC (DisasContext *ctx)
333
{
334
    ctx->exception = POWERPC_EXCP_SYNC;
335 336
}

B
bellard 已提交
337 338 339 340 341
#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)

342 343 344 345 346
#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 已提交
347 348
typedef struct opcode_t {
    unsigned char opc1, opc2, opc3;
T
ths 已提交
349
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
350 351 352 353
    unsigned char pad[5];
#else
    unsigned char pad[1];
#endif
B
bellard 已提交
354
    opc_handler_t handler;
355
    const char *oname;
B
bellard 已提交
356 357
} opcode_t;

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

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

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

    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
}
B
bellard 已提交
404 405 406 407 408 409 410 411 412 413 414 415 416 417
/***                              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 已提交
418 419
/* Trap operand */
EXTRACT_HELPER(TO, 21, 5);
B
bellard 已提交
420 421 422 423

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

B
bellard 已提交
426 427 428 429
/***                            Jump target decoding                       ***/
/* Displacement */
EXTRACT_SHELPER(d, 0, 16);
/* Immediate address */
430
static always_inline target_ulong LI (uint32_t opcode)
B
bellard 已提交
431 432 433 434
{
    return (opcode >> 0) & 0x03FFFFFC;
}

435
static always_inline uint32_t BD (uint32_t opcode)
B
bellard 已提交
436 437 438 439 440 441 442 443 444 445 446 447
{
    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 */
448
static always_inline target_ulong MASK (uint32_t start, uint32_t end)
B
bellard 已提交
449
{
450
    target_ulong ret;
B
bellard 已提交
451

452 453
#if defined(TARGET_PPC64)
    if (likely(start == 0)) {
454
        ret = UINT64_MAX << (63 - end);
455
    } else if (likely(end == 63)) {
456
        ret = UINT64_MAX >> start;
457 458 459
    }
#else
    if (likely(start == 0)) {
460
        ret = UINT32_MAX << (31  - end);
461
    } else if (likely(end == 31)) {
462
        ret = UINT32_MAX >> start;
463 464 465 466 467 468 469 470
    }
#endif
    else {
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
            (((target_ulong)(-1ULL) >> (end)) >> 1);
        if (unlikely(start > end))
            return ~ret;
    }
B
bellard 已提交
471 472 473 474

    return ret;
}

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

    /* Fixed-point unit extensions                                           */
    /*   PowerPC 602 specific                                                */
513
    PPC_602_SPEC       = 0x0000000000000400ULL,
514 515 516 517 518 519
    /*   isel instruction                                                    */
    PPC_ISEL           = 0x0000000000000800ULL,
    /*   popcntb instruction                                                 */
    PPC_POPCNTB        = 0x0000000000001000ULL,
    /*   string load / store                                                 */
    PPC_STRING         = 0x0000000000002000ULL,
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536

    /* 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                                          */
537
    PPC_SPE            = 0x0000000002000000ULL,
538
    /*   PowerPC 2.03 SPE floating-point extension                           */
539
    PPC_SPEFPU         = 0x0000000004000000ULL,
540

541
    /* Optional memory control instructions                                  */
542 543 544 545 546 547 548 549 550
    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                                            */
551
    PPC_CACHE          = 0x0000000200000000ULL,
552
    /*   icbi instruction                                                    */
553
    PPC_CACHE_ICBI     = 0x0000000400000000ULL,
554
    /*   dcbz instruction with fixed cache line size                         */
555
    PPC_CACHE_DCBZ     = 0x0000000800000000ULL,
556
    /*   dcbz instruction with tunable cache line size                       */
557
    PPC_CACHE_DCBZT    = 0x0000001000000000ULL,
558
    /*   dcba instruction                                                    */
559 560 561
    PPC_CACHE_DCBA     = 0x0000002000000000ULL,
    /*   Freescale cache locking instructions                                */
    PPC_CACHE_LOCK     = 0x0000004000000000ULL,
562 563 564

    /* MMU related extensions                                                */
    /*   external control instructions                                       */
565
    PPC_EXTERN         = 0x0000010000000000ULL,
566
    /*   segment register access instructions                                */
567
    PPC_SEGMENT        = 0x0000020000000000ULL,
568
    /*   PowerPC 6xx TLB management instructions                             */
569
    PPC_6xx_TLB        = 0x0000040000000000ULL,
570
    /* PowerPC 74xx TLB management instructions                              */
571
    PPC_74xx_TLB       = 0x0000080000000000ULL,
572
    /*   PowerPC 40x TLB management instructions                             */
573
    PPC_40x_TLB        = 0x0000100000000000ULL,
574
    /*   segment register access instructions for PowerPC 64 "bridge"        */
575
    PPC_SEGMENT_64B    = 0x0000200000000000ULL,
576
    /*   SLB management                                                      */
577
    PPC_SLBI           = 0x0000400000000000ULL,
578

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

/*****************************************************************************/
/* PowerPC instructions table                                                */
613 614 615 616 617
#if HOST_LONG_BITS == 64
#define OPC_ALIGN 8
#else
#define OPC_ALIGN 4
#endif
B
bellard 已提交
618
#if defined(__APPLE__)
619
#define OPCODES_SECTION                                                       \
620
    __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
621
#else
622
#define OPCODES_SECTION                                                       \
623
    __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
624 625
#endif

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

#define GEN_OPCODE_MARK(name)                                                 \
685
OPCODES_SECTION opcode_t opc_##name = {                                       \
B
bellard 已提交
686 687 688
    .opc1 = 0xFF,                                                             \
    .opc2 = 0xFF,                                                             \
    .opc3 = 0xFF,                                                             \
689
    .pad  = { 0, },                                                           \
B
bellard 已提交
690 691
    .handler = {                                                              \
        .inval   = 0x00000000,                                                \
692
        .type = 0x00,                                                         \
B
bellard 已提交
693 694
        .handler = NULL,                                                      \
    },                                                                        \
695
    .oname = stringify(name),                                                 \
B
bellard 已提交
696 697 698 699 700 701
}

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

/* Invalid instruction */
702 703
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
{
704
    GEN_EXCP_INVAL(ctx);
705 706
}

B
bellard 已提交
707 708
static opc_handler_t invalid_handler = {
    .inval   = 0xFFFFFFFF,
709
    .type    = PPC_NONE,
B
bellard 已提交
710 711 712
    .handler = gen_invalid,
};

713 714
/***                           Integer comparison                          ***/

715
static always_inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
716 717 718
{
    int l1, l2, l3;

719 720
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
721 722 723 724 725 726
    tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);

    l1 = gen_new_label();
    l2 = gen_new_label();
    l3 = gen_new_label();
    if (s) {
727 728
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
729
    } else {
730 731
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
732 733 734 735 736 737 738 739 740 741 742
    }
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
    tcg_gen_br(l3);
    gen_set_label(l1);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
    tcg_gen_br(l3);
    gen_set_label(l2);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
    gen_set_label(l3);
}

743
static always_inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
744
{
745 746 747
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
748 749 750
}

#if defined(TARGET_PPC64)
751
static always_inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
752
{
753 754 755
    TCGv t0, t1;
    t0 = tcg_temp_local_new(TCG_TYPE_TL);
    t1 = tcg_temp_local_new(TCG_TYPE_TL);
756
    if (s) {
757 758
        tcg_gen_ext32s_tl(t0, arg0);
        tcg_gen_ext32s_tl(t1, arg1);
759
    } else {
760 761
        tcg_gen_ext32u_tl(t0, arg0);
        tcg_gen_ext32u_tl(t1, arg1);
762
    }
763 764 765
    gen_op_cmp(t0, t1, s, crf);
    tcg_temp_free(t1);
    tcg_temp_free(t0);
766 767
}

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

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

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

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

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

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

/* isel (PowerPC 2.03 specification) */
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
{
    int l1, l2;
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;
844
    TCGv t0;
845 846 847 848 849

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

    mask = 1 << (3 - (bi & 0x03));
850 851 852
    t0 = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
853 854 855 856 857 858 859 860 861 862
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    else
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    gen_set_label(l2);
}

B
bellard 已提交
863 864
/***                           Integer arithmetic                          ***/

865 866 867 868
static always_inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, TCGv arg1, TCGv arg2, int sub)
{
    int l1;
    TCGv t0;
B
bellard 已提交
869

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

897 898 899
static always_inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, TCGv arg2, int sub)
{
    int l1 = gen_new_label();
900 901

#if defined(TARGET_PPC64)
902 903 904 905
    if (!(ctx->sf_mode)) {
        TCGv t0, t1;
        t0 = tcg_temp_new(TCG_TYPE_TL);
        t1 = tcg_temp_new(TCG_TYPE_TL);
906

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

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

931 932 933 934 935 936
    if ((!compute_ca && !compute_ov) ||
        (GET_TCGV(ret) != GET_TCGV(arg1) && GET_TCGV(ret) != GET_TCGV(arg2)))  {
        t0 = ret;
    } else {
        t0 = tcg_temp_local_new(TCG_TYPE_TL);
    }
B
bellard 已提交
937

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

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

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

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

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

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

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

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

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

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

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

static always_inline void gen_op_arith_divw (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                             int sign, int compute_ov)
1069
{
1070 1071 1072 1073
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    TCGv t0 = tcg_temp_local_new(TCG_TYPE_I32);
    TCGv t1 = tcg_temp_local_new(TCG_TYPE_I32);
1074

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

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

/* mulhw  mulhw. */
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER)
1172
{
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
    TCGv t0, t1;

    t0 = tcg_temp_new(TCG_TYPE_I64);
    t1 = tcg_temp_new(TCG_TYPE_I64);
#if defined(TARGET_PPC64)
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
#else
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1193
}
1194 1195
/* mulhwu  mulhwu.  */
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER)
1196
{
1197 1198 1199 1200
    TCGv t0, t1;

    t0 = tcg_temp_new(TCG_TYPE_I64);
    t1 = tcg_temp_new(TCG_TYPE_I64);
1201
#if defined(TARGET_PPC64)
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
    tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
#else
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mul_i64(t0, t0, t1);
    tcg_gen_shri_i64(t0, t0, 32);
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
#endif
    tcg_temp_free(t0);
    tcg_temp_free(t1);
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1217
}
1218 1219
/* mullw  mullw. */
GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER)
1220
{
1221 1222
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
                   cpu_gpr[rB(ctx->opcode)]);
1223
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1224 1225
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1226
}
1227 1228
/* mullwo  mullwo. */
GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER)
1229
{
1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
    int l1;
    TCGv t0, t1;

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

/* neg neg. nego nego. */
static always_inline void gen_op_neg (DisasContext *ctx, TCGv ret, TCGv arg1, int ov_check)
1292
{
1293 1294 1295 1296
    int l1, l2;

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

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

1337 1338 1339
    if ((!compute_ca && !compute_ov) ||
        (GET_TCGV(ret) != GET_TCGV(arg1) && GET_TCGV(ret) != GET_TCGV(arg2)))  {
        t0 = ret;
J
j_mayer 已提交
1340
    } else {
1341
        t0 = tcg_temp_local_new(TCG_TYPE_TL);
1342
    }
1343

1344 1345 1346 1347
    if (add_ca) {
        t1 = tcg_temp_local_new(TCG_TYPE_TL);
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
1348
    }
B
bellard 已提交
1349

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1650
    sh = SH(ctx->opcode);
1651 1652 1653 1654 1655 1656 1657
    if (likely(sh == 0 && mb == 0 && me == 31)) {
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
    } else {
        TCGv t0, t1;
        target_ulong mask;

        t0 = tcg_temp_new(TCG_TYPE_TL);
1658 1659 1660 1661 1662 1663 1664 1665 1666
#if defined(TARGET_PPC64)
        t1 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_rotli_i32(t1, t1, sh);
        tcg_gen_extu_i32_i64(t0, t1);
        tcg_temp_free(t1);
#else
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
#endif
1667
#if defined(TARGET_PPC64)
1668 1669
        mb += 32;
        me += 32;
1670
#endif
1671
        mask = MASK(mb, me);
1672
        t1 = tcg_temp_new(TCG_TYPE_TL);
1673 1674 1675 1676 1677 1678
        tcg_gen_andi_tl(t0, t0, mask);
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
    }
1679
    if (unlikely(Rc(ctx->opcode) != 0))
1680
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
B
bellard 已提交
1681 1682 1683 1684 1685
}
/* rlwinm & rlwinm. */
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    uint32_t mb, me, sh;
1686

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/***                       Floating-Point arithmetic                       ***/
2086
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
2087
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
2088
{                                                                             \
2089
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2090
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2091 2092
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2093 2094 2095
    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)]);                     \
2096
    gen_reset_fpstatus();                                                     \
2097 2098 2099 2100
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
A
aurel32 已提交
2101
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2102
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
2103 2104
}

2105 2106 2107
#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);
2108

2109 2110
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2111
{                                                                             \
2112
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2113
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2114 2115
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2116 2117
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);                     \
2118
    gen_reset_fpstatus();                                                     \
2119 2120 2121 2122
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
A
aurel32 已提交
2123
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2124
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
2125
}
2126 2127 2128
#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);
2129

2130 2131
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2132
{                                                                             \
2133
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2134
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2135 2136
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2137 2138
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);                     \
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rC(ctx->opcode)]);                     \
2139
    gen_reset_fpstatus();                                                     \
2140 2141 2142 2143
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
A
aurel32 已提交
2144
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2145
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
2146
}
2147 2148 2149
#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);
2150

2151
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2152
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
2153
{                                                                             \
2154
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2155
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2156 2157
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2158
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);                     \
2159
    gen_reset_fpstatus();                                                     \
2160
    gen_op_f##name();                                                         \
A
aurel32 已提交
2161
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2162
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2163 2164
}

2165
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2166
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)                        \
2167
{                                                                             \
2168
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2169
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2170 2171
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
2172
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);                     \
2173
    gen_reset_fpstatus();                                                     \
2174
    gen_op_f##name();                                                         \
A
aurel32 已提交
2175
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
2176
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
2177 2178
}

2179
/* fadd - fadds */
2180
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2181
/* fdiv - fdivs */
2182
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2183
/* fmul - fmuls */
2184
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
2185

2186
/* fre */
2187
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2188

2189
/* fres */
2190
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
2191

2192
/* frsqrte */
2193 2194 2195 2196 2197 2198 2199 2200
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();
}
2201
GEN_FLOAT_BS(rsqrtes, 0x3B, 0x1A, 1, PPC_FLOAT_FRSQRTES);
B
bellard 已提交
2202

2203
/* fsel */
2204
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2205
/* fsub - fsubs */
2206
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
2207 2208
/* Optional: */
/* fsqrt */
2209
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
2210
{
2211
    if (unlikely(!ctx->fpu_enabled)) {
2212
        GEN_EXCP_NO_FP(ctx);
2213 2214
        return;
    }
A
aurel32 已提交
2215
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
2216
    gen_reset_fpstatus();
2217
    gen_op_fsqrt();
A
aurel32 已提交
2218
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2219
    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
2220
}
B
bellard 已提交
2221

2222
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
B
bellard 已提交
2223
{
2224
    if (unlikely(!ctx->fpu_enabled)) {
2225
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2226 2227
        return;
    }
A
aurel32 已提交
2228
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
2229
    gen_reset_fpstatus();
2230 2231
    gen_op_fsqrt();
    gen_op_frsp();
A
aurel32 已提交
2232
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2233
    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
B
bellard 已提交
2234 2235 2236
}

/***                     Floating-Point multiply-and-add                   ***/
2237
/* fmadd - fmadds */
2238
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2239
/* fmsub - fmsubs */
2240
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2241
/* fnmadd - fnmadds */
2242
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2243
/* fnmsub - fnmsubs */
2244
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
2245 2246 2247

/***                     Floating-Point round & convert                    ***/
/* fctiw */
2248
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2249
/* fctiwz */
2250
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
2251
/* frsp */
2252
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
2253 2254
#if defined(TARGET_PPC64)
/* fcfid */
2255
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
2256
/* fctid */
2257
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2258
/* fctidz */
2259
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
2260
#endif
B
bellard 已提交
2261

2262
/* frin */
2263
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2264
/* friz */
2265
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2266
/* frip */
2267
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2268
/* frim */
2269
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2270

B
bellard 已提交
2271 2272
/***                         Floating-Point compare                        ***/
/* fcmpo */
2273
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
B
bellard 已提交
2274
{
2275
    if (unlikely(!ctx->fpu_enabled)) {
2276
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2277 2278
        return;
    }
A
aurel32 已提交
2279 2280
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
2281
    gen_reset_fpstatus();
2282
    tcg_gen_helper_1_0(helper_fcmpo, cpu_crf[crfD(ctx->opcode)]);
2283
    gen_op_float_check_status();
B
bellard 已提交
2284 2285 2286
}

/* fcmpu */
2287
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
B
bellard 已提交
2288
{
2289
    if (unlikely(!ctx->fpu_enabled)) {
2290
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2291 2292
        return;
    }
A
aurel32 已提交
2293 2294
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
2295
    gen_reset_fpstatus();
2296
    tcg_gen_helper_1_0(helper_fcmpu, cpu_crf[crfD(ctx->opcode)]);
2297
    gen_op_float_check_status();
B
bellard 已提交
2298 2299
}

2300 2301
/***                         Floating-point move                           ***/
/* fabs */
2302 2303
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2304 2305

/* fmr  - fmr. */
2306
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2307 2308
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
{
2309
    if (unlikely(!ctx->fpu_enabled)) {
2310
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2311 2312
        return;
    }
A
aurel32 已提交
2313 2314
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2315
    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
2316 2317 2318
}

/* fnabs */
2319 2320
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2321
/* fneg */
2322 2323
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2324

B
bellard 已提交
2325 2326 2327 2328
/***                  Floating-Point status & ctrl register                ***/
/* mcrfs */
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
{
2329 2330
    int bfa;

2331
    if (unlikely(!ctx->fpu_enabled)) {
2332
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2333 2334
        return;
    }
2335 2336
    gen_optimize_fprf();
    bfa = 4 * (7 - crfS(ctx->opcode));
2337 2338
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2339
    gen_op_fpscr_resetbit(~(0xF << bfa));
B
bellard 已提交
2340 2341 2342 2343 2344
}

/* mffs */
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
{
2345
    if (unlikely(!ctx->fpu_enabled)) {
2346
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2347 2348
        return;
    }
2349 2350 2351
    gen_optimize_fprf();
    gen_reset_fpstatus();
    gen_op_load_fpscr_FT0();
A
aurel32 已提交
2352
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2353
    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2354 2355 2356 2357 2358
}

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

2361
    if (unlikely(!ctx->fpu_enabled)) {
2362
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2363 2364
        return;
    }
2365 2366 2367 2368 2369 2370
    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)) {
2371
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2372
    }
B
bellard 已提交
2373 2374 2375 2376 2377
}

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

2380
    if (unlikely(!ctx->fpu_enabled)) {
2381
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2382 2383
        return;
    }
2384 2385 2386 2387 2388 2389 2390
    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)) {
2391
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2392 2393 2394
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2395 2396 2397 2398 2399
}

/* mtfsf */
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
{
2400
    if (unlikely(!ctx->fpu_enabled)) {
2401
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2402 2403
        return;
    }
2404
    gen_optimize_fprf();
A
aurel32 已提交
2405
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
2406
    gen_reset_fpstatus();
2407
    gen_op_store_fpscr(FM(ctx->opcode));
2408
    if (unlikely(Rc(ctx->opcode) != 0)) {
2409
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2410 2411 2412
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2413 2414 2415 2416 2417
}

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

2420
    if (unlikely(!ctx->fpu_enabled)) {
2421
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2422 2423
        return;
    }
2424 2425 2426
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
    gen_optimize_fprf();
2427
    tcg_gen_movi_i64(cpu_FT[0], FPIMM(ctx->opcode) << (4 * sh));
2428 2429 2430
    gen_reset_fpstatus();
    gen_op_store_fpscr(1 << sh);
    if (unlikely(Rc(ctx->opcode) != 0)) {
2431
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2432 2433 2434
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2435 2436
}

2437 2438
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2439 2440
static always_inline void gen_addr_imm_index (TCGv EA,
                                              DisasContext *ctx,
2441
                                              target_long maskl)
2442 2443 2444
{
    target_long simm = SIMM(ctx->opcode);

2445
    simm &= ~maskl;
2446 2447 2448 2449 2450 2451
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(EA, simm);
    else if (likely(simm != 0))
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
    else
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2452 2453
}

2454 2455
static always_inline void gen_addr_reg_index (TCGv EA,
                                              DisasContext *ctx)
2456
{
2457 2458 2459 2460
    if (rA(ctx->opcode) == 0)
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
    else
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2461 2462
}

2463 2464
static always_inline void gen_addr_register (TCGv EA,
                                             DisasContext *ctx)
2465
{
2466 2467 2468 2469
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(EA, 0);
    else
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2470 2471
}

2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482
#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
2483
#if defined(CONFIG_USER_ONLY)
2484
#if defined(TARGET_PPC64)
2485
#define NB_MEM_FUNCS 4
2486
#else
2487
#define NB_MEM_FUNCS 2
2488
#endif
2489 2490
#define GEN_MEM_FUNCS(name)                                                   \
    _GEN_MEM_FUNCS(name, raw)
2491
#else
2492
#if defined(TARGET_PPC64)
2493
#define NB_MEM_FUNCS 12
2494
#else
2495
#define NB_MEM_FUNCS 6
2496
#endif
2497 2498 2499 2500 2501 2502 2503 2504
#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])()
2505
#define OP_LD_TABLE(width)                                                    \
2506 2507
static GenOpFunc *gen_op_l##width[NB_MEM_FUNCS] = {                           \
    GEN_MEM_FUNCS(l##width),                                                  \
2508 2509
};
#define OP_ST_TABLE(width)                                                    \
2510 2511
static GenOpFunc *gen_op_st##width[NB_MEM_FUNCS] = {                          \
    GEN_MEM_FUNCS(st##width),                                                 \
2512
};
2513

A
aurel32 已提交
2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552

#if defined(TARGET_PPC64)
#define GEN_QEMU_LD_PPC64(width)                                                 \
static always_inline void gen_qemu_ld##width##_ppc64(TCGv t0, TCGv t1, int flags)\
{                                                                                \
    if (likely(flags & 2))                                                       \
        tcg_gen_qemu_ld##width(t0, t1, flags >> 2);                              \
    else {                                                                       \
        TCGv addr = tcg_temp_new(TCG_TYPE_TL);                                   \
        tcg_gen_ext32u_tl(addr, t1);                                             \
        tcg_gen_qemu_ld##width(t0, addr, flags >> 2);                            \
        tcg_temp_free(addr);                                                     \
    }                                                                            \
}
GEN_QEMU_LD_PPC64(8u)
GEN_QEMU_LD_PPC64(8s)
GEN_QEMU_LD_PPC64(16u)
GEN_QEMU_LD_PPC64(16s)
GEN_QEMU_LD_PPC64(32u)
GEN_QEMU_LD_PPC64(32s)
GEN_QEMU_LD_PPC64(64)

#define GEN_QEMU_ST_PPC64(width)                                                 \
static always_inline void gen_qemu_st##width##_ppc64(TCGv t0, TCGv t1, int flags)\
{                                                                                \
    if (likely(flags & 2))                                                       \
        tcg_gen_qemu_st##width(t0, t1, flags >> 2);                              \
    else {                                                                       \
        TCGv addr = tcg_temp_new(TCG_TYPE_TL);                                   \
        tcg_gen_ext32u_tl(addr, t1);                                             \
        tcg_gen_qemu_st##width(t0, addr, flags >> 2);                            \
        tcg_temp_free(addr);                                                     \
    }                                                                            \
}
GEN_QEMU_ST_PPC64(8)
GEN_QEMU_ST_PPC64(16)
GEN_QEMU_ST_PPC64(32)
GEN_QEMU_ST_PPC64(64)

2553
static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2554
{
2555
    gen_qemu_ld8u_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2556 2557
}

2558
static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2559
{
2560
    gen_qemu_ld8s_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2561 2562
}

2563
static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2564 2565
{
    if (unlikely(flags & 1)) {
2566 2567 2568 2569 2570 2571 2572
        TCGv t0;
        gen_qemu_ld16u_ppc64(arg0, arg1, flags);
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap16_i32(t0, t0);
        tcg_gen_extu_i32_tl(arg0, t0);
        tcg_temp_free(t0);
A
aurel32 已提交
2573
    } else
2574
        gen_qemu_ld16u_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2575 2576
}

2577
static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2578 2579
{
    if (unlikely(flags & 1)) {
2580 2581 2582 2583 2584 2585 2586 2587
        TCGv t0;
        gen_qemu_ld16u_ppc64(arg0, arg1, flags);
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap16_i32(t0, t0);
        tcg_gen_extu_i32_tl(arg0, t0);
        tcg_gen_ext16s_tl(arg0, arg0);
        tcg_temp_free(t0);
A
aurel32 已提交
2588
    } else
2589
        gen_qemu_ld16s_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2590 2591
}

2592
static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2593 2594
{
    if (unlikely(flags & 1)) {
2595 2596 2597 2598 2599 2600 2601
        TCGv t0;
        gen_qemu_ld32u_ppc64(arg0, arg1, flags);
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap_i32(t0, t0);
        tcg_gen_extu_i32_tl(arg0, t0);
        tcg_temp_free(t0);
A
aurel32 已提交
2602
    } else
2603
        gen_qemu_ld32u_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2604 2605
}

2606
static always_inline void gen_qemu_ld32s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2607 2608
{
    if (unlikely(flags & 1)) {
2609 2610 2611 2612 2613 2614 2615
        TCGv t0;
        gen_qemu_ld32u_ppc64(arg0, arg1, flags);
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap_i32(t0, t0);
        tcg_gen_ext_i32_tl(arg0, t0);
        tcg_temp_free(t0);
A
aurel32 已提交
2616
    } else
2617
        gen_qemu_ld32s_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2618 2619
}

2620
static always_inline void gen_qemu_ld64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2621
{
2622
    gen_qemu_ld64_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2623
    if (unlikely(flags & 1))
2624
        tcg_gen_bswap_i64(arg0, arg0);
A
aurel32 已提交
2625 2626
}

2627
static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2628
{
2629
    gen_qemu_st8_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2630 2631
}

2632
static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2633 2634
{
    if (unlikely(flags & 1)) {
2635 2636 2637 2638 2639 2640 2641 2642 2643 2644
        TCGv t0, t1;
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_ext16u_i32(t0, t0);
        tcg_gen_bswap16_i32(t0, t0);
        t1 = tcg_temp_new(TCG_TYPE_I64);
        tcg_gen_extu_i32_tl(t1, t0);
        tcg_temp_free(t0);
        gen_qemu_st16_ppc64(t1, arg1, flags);
        tcg_temp_free(t1);
A
aurel32 已提交
2645
    } else
2646
        gen_qemu_st16_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2647 2648
}

2649
static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2650 2651
{
    if (unlikely(flags & 1)) {
2652 2653 2654 2655 2656 2657 2658 2659 2660
        TCGv t0, t1;
        t0 = tcg_temp_new(TCG_TYPE_I32);
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap_i32(t0, t0);
        t1 = tcg_temp_new(TCG_TYPE_I64);
        tcg_gen_extu_i32_tl(t1, t0);
        tcg_temp_free(t0);
        gen_qemu_st32_ppc64(t1, arg1, flags);
        tcg_temp_free(t1);
A
aurel32 已提交
2661
    } else
2662
        gen_qemu_st32_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2663 2664
}

2665
static always_inline void gen_qemu_st64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2666 2667
{
    if (unlikely(flags & 1)) {
2668 2669 2670 2671
        TCGv t0 = tcg_temp_new(TCG_TYPE_I64);
        tcg_gen_bswap_i64(t0, arg0);
        gen_qemu_st64_ppc64(t0, arg1, flags);
        tcg_temp_free(t0);
A
aurel32 已提交
2672
    } else
2673
        gen_qemu_st64_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2674 2675 2676 2677 2678
}


#else /* defined(TARGET_PPC64) */
#define GEN_QEMU_LD_PPC32(width)                                                 \
2679
static always_inline void gen_qemu_ld##width##_ppc32(TCGv arg0, TCGv arg1, int flags)\
A
aurel32 已提交
2680
{                                                                                \
2681
    tcg_gen_qemu_ld##width(arg0, arg1, flags >> 1);                                  \
A
aurel32 已提交
2682 2683 2684 2685 2686 2687 2688 2689 2690 2691
}
GEN_QEMU_LD_PPC32(8u)
GEN_QEMU_LD_PPC32(8s)
GEN_QEMU_LD_PPC32(16u)
GEN_QEMU_LD_PPC32(16s)
GEN_QEMU_LD_PPC32(32u)
GEN_QEMU_LD_PPC32(32s)
GEN_QEMU_LD_PPC32(64)

#define GEN_QEMU_ST_PPC32(width)                                                 \
2692
static always_inline void gen_qemu_st##width##_ppc32(TCGv arg0, TCGv arg1, int flags)\
A
aurel32 已提交
2693
{                                                                                \
2694
    tcg_gen_qemu_st##width(arg0, arg1, flags >> 1);                                  \
A
aurel32 已提交
2695 2696 2697 2698 2699 2700
}
GEN_QEMU_ST_PPC32(8)
GEN_QEMU_ST_PPC32(16)
GEN_QEMU_ST_PPC32(32)
GEN_QEMU_ST_PPC32(64)

2701
static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2702
{
2703
    gen_qemu_ld8u_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2704 2705
}

2706
static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2707
{
2708
    gen_qemu_ld8s_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2709 2710
}

2711
static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2712
{
2713
    gen_qemu_ld16u_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2714
    if (unlikely(flags & 1))
2715
        tcg_gen_bswap16_i32(arg0, arg0);
A
aurel32 已提交
2716 2717
}

2718
static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2719 2720
{
    if (unlikely(flags & 1)) {
2721 2722 2723
        gen_qemu_ld16u_ppc32(arg0, arg1, flags);
        tcg_gen_bswap16_i32(arg0, arg0);
        tcg_gen_ext16s_i32(arg0, arg0);
A
aurel32 已提交
2724
    } else
2725
        gen_qemu_ld16s_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2726 2727
}

2728
static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2729
{
2730
    gen_qemu_ld32u_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2731
    if (unlikely(flags & 1))
2732
        tcg_gen_bswap_i32(arg0, arg0);
A
aurel32 已提交
2733 2734
}

2735
static always_inline void gen_qemu_ld64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2736
{
2737
    gen_qemu_ld64_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2738
    if (unlikely(flags & 1))
2739
        tcg_gen_bswap_i64(arg0, arg0);
A
aurel32 已提交
2740 2741
}

2742
static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2743
{
2744
    gen_qemu_st8_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2745 2746
}

2747
static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2748 2749 2750
{
    if (unlikely(flags & 1)) {
        TCGv temp = tcg_temp_new(TCG_TYPE_I32);
2751
        tcg_gen_ext16u_i32(temp, arg0);
A
aurel32 已提交
2752
        tcg_gen_bswap16_i32(temp, temp);
2753
        gen_qemu_st16_ppc32(temp, arg1, flags);
A
aurel32 已提交
2754
        tcg_temp_free(temp);
A
aurel32 已提交
2755
    } else
2756
        gen_qemu_st16_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2757 2758
}

2759
static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2760 2761 2762
{
    if (unlikely(flags & 1)) {
        TCGv temp = tcg_temp_new(TCG_TYPE_I32);
2763
        tcg_gen_bswap_i32(temp, arg0);
2764
        gen_qemu_st32_ppc32(temp, arg1, flags);
A
aurel32 已提交
2765
        tcg_temp_free(temp);
A
aurel32 已提交
2766
    } else
2767
        gen_qemu_st32_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2768 2769
}

2770
static always_inline void gen_qemu_st64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2771 2772 2773
{
    if (unlikely(flags & 1)) {
        TCGv temp = tcg_temp_new(TCG_TYPE_I64);
2774
        tcg_gen_bswap_i64(temp, arg0);
2775
        gen_qemu_st64_ppc32(temp, arg1, flags);
A
aurel32 已提交
2776
        tcg_temp_free(temp);
A
aurel32 已提交
2777
    } else
2778
        gen_qemu_st64_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2779 2780 2781 2782
}

#endif

2783 2784
#define GEN_LD(width, opc, type)                                              \
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
B
bellard 已提交
2785
{                                                                             \
A
aurel32 已提交
2786 2787 2788 2789
    TCGv EA = tcg_temp_new(TCG_TYPE_TL);                                      \
    gen_addr_imm_index(EA, ctx, 0);                                           \
    gen_qemu_ld##width(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2790 2791
}

2792 2793
#define GEN_LDU(width, opc, type)                                             \
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
B
bellard 已提交
2794
{                                                                             \
A
aurel32 已提交
2795
    TCGv EA;                                                                  \
2796 2797
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2798
        GEN_EXCP_INVAL(ctx);                                                  \
2799
        return;                                                               \
2800
    }                                                                         \
A
aurel32 已提交
2801
    EA = tcg_temp_new(TCG_TYPE_TL);                                           \
J
j_mayer 已提交
2802
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2803
        gen_addr_imm_index(EA, ctx, 0x03);                                    \
J
j_mayer 已提交
2804
    else                                                                      \
A
aurel32 已提交
2805 2806 2807 2808
        gen_addr_imm_index(EA, ctx, 0);                                       \
    gen_qemu_ld##width(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2809 2810
}

2811 2812
#define GEN_LDUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2813
{                                                                             \
A
aurel32 已提交
2814
    TCGv EA;                                                                  \
2815 2816
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2817
        GEN_EXCP_INVAL(ctx);                                                  \
2818
        return;                                                               \
2819
    }                                                                         \
A
aurel32 已提交
2820 2821 2822 2823 2824
    EA = tcg_temp_new(TCG_TYPE_TL);                                           \
    gen_addr_reg_index(EA, ctx);                                              \
    gen_qemu_ld##width(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2825 2826
}

2827 2828
#define GEN_LDX(width, opc2, opc3, type)                                      \
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
B
bellard 已提交
2829
{                                                                             \
A
aurel32 已提交
2830 2831 2832 2833
    TCGv EA = tcg_temp_new(TCG_TYPE_TL);                                      \
    gen_addr_reg_index(EA, ctx);                                              \
    gen_qemu_ld##width(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2834 2835
}

2836 2837 2838 2839 2840
#define GEN_LDS(width, op, type)                                              \
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 已提交
2841 2842

/* lbz lbzu lbzux lbzx */
A
aurel32 已提交
2843
GEN_LDS(8u, 0x02, PPC_INTEGER);
B
bellard 已提交
2844
/* lha lhau lhaux lhax */
A
aurel32 已提交
2845
GEN_LDS(16s, 0x0A, PPC_INTEGER);
B
bellard 已提交
2846
/* lhz lhzu lhzux lhzx */
A
aurel32 已提交
2847
GEN_LDS(16u, 0x08, PPC_INTEGER);
B
bellard 已提交
2848
/* lwz lwzu lwzux lwzx */
A
aurel32 已提交
2849
GEN_LDS(32u, 0x00, PPC_INTEGER);
2850 2851
#if defined(TARGET_PPC64)
/* lwaux */
A
aurel32 已提交
2852
GEN_LDUX(32s, 0x15, 0x0B, PPC_64B);
2853
/* lwax */
A
aurel32 已提交
2854
GEN_LDX(32s, 0x15, 0x0A, PPC_64B);
2855
/* ldux */
A
aurel32 已提交
2856
GEN_LDUX(64, 0x15, 0x01, PPC_64B);
2857
/* ldx */
A
aurel32 已提交
2858
GEN_LDX(64, 0x15, 0x00, PPC_64B);
2859 2860
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
{
A
aurel32 已提交
2861
    TCGv EA;
2862 2863 2864
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
2865
            GEN_EXCP_INVAL(ctx);
2866 2867 2868
            return;
        }
    }
A
aurel32 已提交
2869 2870
    EA = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_imm_index(EA, ctx, 0x03);
2871 2872
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
A
aurel32 已提交
2873
        gen_qemu_ld32s(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);
2874 2875
    } else {
        /* ld - ldu */
A
aurel32 已提交
2876
        gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);
2877 2878
    }
    if (Rc(ctx->opcode))
A
aurel32 已提交
2879 2880
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
    tcg_temp_free(EA);
2881
}
2882 2883 2884 2885 2886 2887 2888
/* lq */
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    int ra, rd;
A
aurel32 已提交
2889
    TCGv EA;
2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906

    /* 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;
    }
A
aurel32 已提交
2907 2908 2909 2910 2911 2912
    EA = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_imm_index(EA, ctx, 0x0F);
    gen_qemu_ld64(cpu_gpr[rd], EA, ctx->mem_idx);
    tcg_gen_addi_tl(EA, EA, 8);
    gen_qemu_ld64(cpu_gpr[rd+1], EA, ctx->mem_idx);
    tcg_temp_free(EA);
2913 2914
#endif
}
2915
#endif
B
bellard 已提交
2916 2917

/***                              Integer store                            ***/
2918 2919
#define GEN_ST(width, opc, type)                                              \
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
B
bellard 已提交
2920
{                                                                             \
A
aurel32 已提交
2921 2922 2923 2924
    TCGv EA = tcg_temp_new(TCG_TYPE_TL);                                      \
    gen_addr_imm_index(EA, ctx, 0);                                           \
    gen_qemu_st##width(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx);       \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2925 2926
}

2927 2928
#define GEN_STU(width, opc, type)                                             \
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
B
bellard 已提交
2929
{                                                                             \
A
aurel32 已提交
2930
    TCGv EA;                                                                  \
2931
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2932
        GEN_EXCP_INVAL(ctx);                                                  \
2933
        return;                                                               \
2934
    }                                                                         \
A
aurel32 已提交
2935
    EA = tcg_temp_new(TCG_TYPE_TL);                                           \
J
j_mayer 已提交
2936
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2937
        gen_addr_imm_index(EA, ctx, 0x03);                                    \
J
j_mayer 已提交
2938
    else                                                                      \
A
aurel32 已提交
2939 2940 2941 2942
        gen_addr_imm_index(EA, ctx, 0);                                       \
    gen_qemu_st##width(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2943 2944
}

2945 2946
#define GEN_STUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                \
B
bellard 已提交
2947
{                                                                             \
A
aurel32 已提交
2948
    TCGv EA;                                                                  \
2949
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2950
        GEN_EXCP_INVAL(ctx);                                                  \
2951
        return;                                                               \
2952
    }                                                                         \
A
aurel32 已提交
2953 2954 2955 2956 2957
    EA = tcg_temp_new(TCG_TYPE_TL);                                           \
    gen_addr_reg_index(EA, ctx);                                              \
    gen_qemu_st##width(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2958 2959
}

2960 2961
#define GEN_STX(width, opc2, opc3, type)                                      \
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2962
{                                                                             \
A
aurel32 已提交
2963 2964 2965 2966
    TCGv EA = tcg_temp_new(TCG_TYPE_TL);                                      \
    gen_addr_reg_index(EA, ctx);                                              \
    gen_qemu_st##width(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx);           \
    tcg_temp_free(EA);                                                        \
B
bellard 已提交
2967 2968
}

2969 2970 2971 2972 2973
#define GEN_STS(width, op, type)                                              \
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 已提交
2974 2975

/* stb stbu stbux stbx */
A
aurel32 已提交
2976
GEN_STS(8, 0x06, PPC_INTEGER);
B
bellard 已提交
2977
/* sth sthu sthux sthx */
A
aurel32 已提交
2978
GEN_STS(16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2979
/* stw stwu stwux stwx */
A
aurel32 已提交
2980
GEN_STS(32, 0x04, PPC_INTEGER);
2981
#if defined(TARGET_PPC64)
A
aurel32 已提交
2982 2983
GEN_STUX(64, 0x15, 0x05, PPC_64B);
GEN_STX(64, 0x15, 0x04, PPC_64B);
2984
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2985
{
2986
    int rs;
A
aurel32 已提交
2987
    TCGv EA;
2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999

    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)) {
3000
            GEN_EXCP_INVAL(ctx);
3001 3002
            return;
        }
3003 3004 3005 3006 3007
        if (unlikely(ctx->mem_idx & 1)) {
            /* Little-endian mode is not handled */
            GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
            return;
        }
A
aurel32 已提交
3008 3009 3010 3011 3012 3013
        EA = tcg_temp_new(TCG_TYPE_TL);
        gen_addr_imm_index(EA, ctx, 0x03);
        gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx);
        tcg_gen_addi_tl(EA, EA, 8);
        gen_qemu_st64(cpu_gpr[rs+1], EA, ctx->mem_idx);
        tcg_temp_free(EA);
3014 3015 3016 3017 3018 3019 3020 3021 3022
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
                GEN_EXCP_INVAL(ctx);
                return;
            }
        }
A
aurel32 已提交
3023 3024 3025
        EA = tcg_temp_new(TCG_TYPE_TL);
        gen_addr_imm_index(EA, ctx, 0x03);
        gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx);
3026
        if (Rc(ctx->opcode))
A
aurel32 已提交
3027 3028
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
        tcg_temp_free(EA);
3029 3030 3031
    }
}
#endif
B
bellard 已提交
3032 3033
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
A
aurel32 已提交
3034 3035 3036 3037 3038 3039 3040 3041 3042 3043
void always_inline gen_qemu_ld16ur(TCGv t0, TCGv t1, int flags)
{
    TCGv temp = tcg_temp_new(TCG_TYPE_I32);
    gen_qemu_ld16u(temp, t1, flags);
    tcg_gen_bswap16_i32(temp, temp);
    tcg_gen_extu_i32_tl(t0, temp);
    tcg_temp_free(temp);
}
GEN_LDX(16ur, 0x16, 0x18, PPC_INTEGER);

B
bellard 已提交
3044
/* lwbrx */
A
aurel32 已提交
3045 3046 3047 3048 3049 3050 3051 3052 3053 3054
void always_inline gen_qemu_ld32ur(TCGv t0, TCGv t1, int flags)
{
    TCGv temp = tcg_temp_new(TCG_TYPE_I32);
    gen_qemu_ld32u(temp, t1, flags);
    tcg_gen_bswap_i32(temp, temp);
    tcg_gen_extu_i32_tl(t0, temp);
    tcg_temp_free(temp);
}
GEN_LDX(32ur, 0x16, 0x10, PPC_INTEGER);

B
bellard 已提交
3055
/* sthbrx */
A
aurel32 已提交
3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066
void always_inline gen_qemu_st16r(TCGv t0, TCGv t1, int flags)
{
    TCGv temp = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_trunc_tl_i32(temp, t0);
    tcg_gen_ext16u_i32(temp, temp);
    tcg_gen_bswap16_i32(temp, temp);
    gen_qemu_st16(temp, t1, flags);
    tcg_temp_free(temp);
}
GEN_STX(16r, 0x16, 0x1C, PPC_INTEGER);

B
bellard 已提交
3067
/* stwbrx */
A
aurel32 已提交
3068 3069 3070 3071 3072 3073 3074 3075 3076
void always_inline gen_qemu_st32r(TCGv t0, TCGv t1, int flags)
{
    TCGv temp = tcg_temp_new(TCG_TYPE_I32);
    tcg_gen_trunc_tl_i32(temp, t0);
    tcg_gen_bswap_i32(temp, temp);
    gen_qemu_st32(temp, t1, flags);
    tcg_temp_free(temp);
}
GEN_STX(32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
3077 3078

/***                    Integer load and store multiple                    ***/
3079
#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
3080 3081
static GenOpFunc1 *gen_op_lmw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lmw),
3082
};
3083 3084
static GenOpFunc1 *gen_op_stmw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stmw),
3085
};
3086

B
bellard 已提交
3087 3088 3089
/* lmw */
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
3090
    /* NIP cannot be restored if the memory exception comes from an helper */
3091
    gen_update_nip(ctx, ctx->nip - 4);
3092
    gen_addr_imm_index(cpu_T[0], ctx, 0);
3093
    op_ldstm(lmw, rD(ctx->opcode));
B
bellard 已提交
3094 3095 3096 3097 3098
}

/* stmw */
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
3099
    /* NIP cannot be restored if the memory exception comes from an helper */
3100
    gen_update_nip(ctx, ctx->nip - 4);
3101
    gen_addr_imm_index(cpu_T[0], ctx, 0);
3102
    op_ldstm(stmw, rS(ctx->opcode));
B
bellard 已提交
3103 3104 3105
}

/***                    Integer load and store strings                     ***/
3106 3107
#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)
3108 3109 3110 3111 3112 3113 3114 3115 3116
/* 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
3117 3118
static GenOpFunc1 *gen_op_lswi[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lswi),
3119
};
3120 3121 3122 3123 3124 3125 3126 3127
#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
3128 3129
static GenOpFunc3 *gen_op_lswx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lswx),
3130
};
3131 3132 3133 3134 3135 3136 3137 3138
#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
3139 3140
static GenOpFunc1 *gen_op_stsw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stsw),
3141 3142
};

B
bellard 已提交
3143
/* lswi */
3144
/* PowerPC32 specification says we must generate an exception if
3145 3146 3147 3148
 * 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...
 */
3149
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
B
bellard 已提交
3150 3151 3152
{
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
3153
    int ra = rA(ctx->opcode);
B
bellard 已提交
3154 3155 3156 3157 3158
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
3159 3160 3161
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
3162 3163
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
3164
        return;
B
bellard 已提交
3165
    }
3166
    /* NIP cannot be restored if the memory exception comes from an helper */
3167
    gen_update_nip(ctx, ctx->nip - 4);
3168
    gen_addr_register(cpu_T[0], ctx);
3169
    tcg_gen_movi_tl(cpu_T[1], nb);
3170
    op_ldsts(lswi, start);
B
bellard 已提交
3171 3172 3173
}

/* lswx */
3174
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
B
bellard 已提交
3175
{
3176 3177 3178
    int ra = rA(ctx->opcode);
    int rb = rB(ctx->opcode);

3179
    /* NIP cannot be restored if the memory exception comes from an helper */
3180
    gen_update_nip(ctx, ctx->nip - 4);
3181
    gen_addr_reg_index(cpu_T[0], ctx);
3182 3183
    if (ra == 0) {
        ra = rb;
B
bellard 已提交
3184
    }
A
aurel32 已提交
3185
    tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F);
3186
    op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
B
bellard 已提交
3187 3188 3189
}

/* stswi */
3190
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
B
bellard 已提交
3191
{
B
bellard 已提交
3192 3193
    int nb = NB(ctx->opcode);

3194
    /* NIP cannot be restored if the memory exception comes from an helper */
3195
    gen_update_nip(ctx, ctx->nip - 4);
3196
    gen_addr_register(cpu_T[0], ctx);
B
bellard 已提交
3197 3198
    if (nb == 0)
        nb = 32;
3199
    tcg_gen_movi_tl(cpu_T[1], nb);
3200
    op_ldsts(stsw, rS(ctx->opcode));
B
bellard 已提交
3201 3202 3203
}

/* stswx */
3204
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
B
bellard 已提交
3205
{
3206
    /* NIP cannot be restored if the memory exception comes from an helper */
3207
    gen_update_nip(ctx, ctx->nip - 4);
3208
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
3209
    tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F);
3210
    op_ldsts(stsw, rS(ctx->opcode));
B
bellard 已提交
3211 3212 3213 3214
}

/***                        Memory synchronisation                         ***/
/* eieio */
3215
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
B
bellard 已提交
3216 3217 3218 3219
{
}

/* isync */
3220
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
B
bellard 已提交
3221
{
3222
    GEN_STOP(ctx);
B
bellard 已提交
3223 3224
}

3225 3226
#define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
3227 3228
static GenOpFunc *gen_op_lwarx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lwarx),
3229
};
3230 3231
static GenOpFunc *gen_op_stwcx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stwcx),
B
bellard 已提交
3232
};
3233

3234
/* lwarx */
3235
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
B
bellard 已提交
3236
{
3237 3238
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3239
    gen_addr_reg_index(cpu_T[0], ctx);
B
bellard 已提交
3240
    op_lwarx();
A
aurel32 已提交
3241
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
B
bellard 已提交
3242 3243 3244
}

/* stwcx. */
3245
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
B
bellard 已提交
3246
{
3247 3248
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3249
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
3250
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
3251
    op_stwcx();
B
bellard 已提交
3252 3253
}

J
j_mayer 已提交
3254 3255 3256
#if defined(TARGET_PPC64)
#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
3257 3258
static GenOpFunc *gen_op_ldarx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(ldarx),
J
j_mayer 已提交
3259
};
3260 3261
static GenOpFunc *gen_op_stdcx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stdcx),
J
j_mayer 已提交
3262 3263 3264
};

/* ldarx */
3265
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
J
j_mayer 已提交
3266
{
3267 3268
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3269
    gen_addr_reg_index(cpu_T[0], ctx);
J
j_mayer 已提交
3270
    op_ldarx();
A
aurel32 已提交
3271
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
J
j_mayer 已提交
3272 3273 3274
}

/* stdcx. */
3275
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
J
j_mayer 已提交
3276
{
3277 3278
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3279
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
3280
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
J
j_mayer 已提交
3281 3282 3283 3284
    op_stdcx();
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3285
/* sync */
3286
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
B
bellard 已提交
3287 3288 3289
{
}

3290 3291 3292 3293
/* wait */
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
{
    /* Stop translation, as the CPU is supposed to sleep from now */
3294 3295
    gen_op_wait();
    GEN_EXCP(ctx, EXCP_HLT, 1);
3296 3297
}

B
bellard 已提交
3298
/***                         Floating-point load                           ***/
3299 3300
#define GEN_LDF(width, opc, type)                                             \
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
B
bellard 已提交
3301
{                                                                             \
3302
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3303
        GEN_EXCP_NO_FP(ctx);                                                  \
3304 3305
        return;                                                               \
    }                                                                         \
3306
    gen_addr_imm_index(cpu_T[0], ctx, 0);                                     \
3307
    op_ldst(l##width);                                                        \
A
aurel32 已提交
3308
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
B
bellard 已提交
3309 3310
}

3311 3312
#define GEN_LDUF(width, opc, type)                                            \
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
B
bellard 已提交
3313
{                                                                             \
3314
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3315
        GEN_EXCP_NO_FP(ctx);                                                  \
3316 3317
        return;                                                               \
    }                                                                         \
3318
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3319
        GEN_EXCP_INVAL(ctx);                                                  \
3320
        return;                                                               \
3321
    }                                                                         \
3322
    gen_addr_imm_index(cpu_T[0], ctx, 0);                                     \
3323
    op_ldst(l##width);                                                        \
A
aurel32 已提交
3324
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
A
aurel32 已提交
3325
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
3326 3327
}

3328 3329
#define GEN_LDUXF(width, opc, type)                                           \
GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                  \
B
bellard 已提交
3330
{                                                                             \
3331
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3332
        GEN_EXCP_NO_FP(ctx);                                                  \
3333 3334
        return;                                                               \
    }                                                                         \
3335
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3336
        GEN_EXCP_INVAL(ctx);                                                  \
3337
        return;                                                               \
3338
    }                                                                         \
3339
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
3340
    op_ldst(l##width);                                                        \
A
aurel32 已提交
3341
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
A
aurel32 已提交
3342
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
3343 3344
}

3345 3346
#define GEN_LDXF(width, opc2, opc3, type)                                     \
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
B
bellard 已提交
3347
{                                                                             \
3348
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3349
        GEN_EXCP_NO_FP(ctx);                                                  \
3350 3351
        return;                                                               \
    }                                                                         \
3352
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
3353
    op_ldst(l##width);                                                        \
A
aurel32 已提交
3354
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);                     \
B
bellard 已提交
3355 3356
}

3357
#define GEN_LDFS(width, op, type)                                             \
3358
OP_LD_TABLE(width);                                                           \
3359 3360 3361 3362
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 已提交
3363 3364

/* lfd lfdu lfdux lfdx */
3365
GEN_LDFS(fd, 0x12, PPC_FLOAT);
B
bellard 已提交
3366
/* lfs lfsu lfsux lfsx */
3367
GEN_LDFS(fs, 0x10, PPC_FLOAT);
B
bellard 已提交
3368 3369

/***                         Floating-point store                          ***/
3370 3371
#define GEN_STF(width, opc, type)                                             \
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
B
bellard 已提交
3372
{                                                                             \
3373
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3374
        GEN_EXCP_NO_FP(ctx);                                                  \
3375 3376
        return;                                                               \
    }                                                                         \
3377
    gen_addr_imm_index(cpu_T[0], ctx, 0);                                     \
A
aurel32 已提交
3378
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
3379
    op_ldst(st##width);                                                       \
B
bellard 已提交
3380 3381
}

3382 3383
#define GEN_STUF(width, opc, type)                                            \
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
B
bellard 已提交
3384
{                                                                             \
3385
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3386
        GEN_EXCP_NO_FP(ctx);                                                  \
3387 3388
        return;                                                               \
    }                                                                         \
3389
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3390
        GEN_EXCP_INVAL(ctx);                                                  \
3391
        return;                                                               \
3392
    }                                                                         \
3393
    gen_addr_imm_index(cpu_T[0], ctx, 0);                                     \
A
aurel32 已提交
3394
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
3395
    op_ldst(st##width);                                                       \
A
aurel32 已提交
3396
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
3397 3398
}

3399 3400
#define GEN_STUXF(width, opc, type)                                           \
GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                 \
B
bellard 已提交
3401
{                                                                             \
3402
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3403
        GEN_EXCP_NO_FP(ctx);                                                  \
3404 3405
        return;                                                               \
    }                                                                         \
3406
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3407
        GEN_EXCP_INVAL(ctx);                                                  \
3408
        return;                                                               \
3409
    }                                                                         \
3410
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
A
aurel32 已提交
3411
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
3412
    op_ldst(st##width);                                                       \
A
aurel32 已提交
3413
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);                       \
B
bellard 已提交
3414 3415
}

3416 3417
#define GEN_STXF(width, opc2, opc3, type)                                     \
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
3418
{                                                                             \
3419
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3420
        GEN_EXCP_NO_FP(ctx);                                                  \
3421 3422
        return;                                                               \
    }                                                                         \
3423
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
A
aurel32 已提交
3424
    tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);                     \
3425
    op_ldst(st##width);                                                       \
B
bellard 已提交
3426 3427
}

3428
#define GEN_STFS(width, op, type)                                             \
3429
OP_ST_TABLE(width);                                                           \
3430 3431 3432 3433
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 已提交
3434 3435

/* stfd stfdu stfdux stfdx */
3436
GEN_STFS(fd, 0x16, PPC_FLOAT);
B
bellard 已提交
3437
/* stfs stfsu stfsux stfsx */
3438
GEN_STFS(fs, 0x14, PPC_FLOAT);
B
bellard 已提交
3439 3440 3441

/* Optional: */
/* stfiwx */
J
j_mayer 已提交
3442 3443
OP_ST_TABLE(fiw);
GEN_STXF(fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
3444 3445

/***                                Branch                                 ***/
3446 3447
static always_inline void gen_goto_tb (DisasContext *ctx, int n,
                                       target_ulong dest)
3448 3449 3450
{
    TranslationBlock *tb;
    tb = ctx->tb;
3451 3452 3453 3454
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        dest = (uint32_t) dest;
#endif
B
bellard 已提交
3455
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3456
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
3457
        tcg_gen_goto_tb(n);
3458
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
B
bellard 已提交
3459
        tcg_gen_exit_tb((long)tb + n);
3460
    } else {
3461
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3462 3463
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
A
aurel32 已提交
3464
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475
                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 已提交
3476
        tcg_gen_exit_tb(0);
3477
    }
B
bellard 已提交
3478 3479
}

3480
static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
3481 3482
{
#if defined(TARGET_PPC64)
3483 3484
    if (ctx->sf_mode == 0)
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3485 3486
    else
#endif
3487
        tcg_gen_movi_tl(cpu_lr, nip);
3488 3489
}

B
bellard 已提交
3490 3491 3492
/* b ba bl bla */
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
3493
    target_ulong li, target;
B
bellard 已提交
3494

3495
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
3496
    /* sign extend LI */
3497
#if defined(TARGET_PPC64)
3498 3499 3500
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
3501
#endif
3502
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3503
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
3504
        target = ctx->nip + li - 4;
B
bellard 已提交
3505
    else
3506
        target = li;
3507 3508
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3509
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3510 3511
}

3512 3513 3514 3515
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

3516
static always_inline void gen_bcond (DisasContext *ctx, int type)
3517 3518
{
    uint32_t bo = BO(ctx->opcode);
3519 3520
    int l1 = gen_new_label();
    TCGv target;
3521

3522
    ctx->exception = POWERPC_EXCP_BRANCH;
3523 3524 3525 3526 3527 3528
    if (type == BCOND_LR || type == BCOND_CTR) {
        target = tcg_temp_local_new(TCG_TYPE_TL);
        if (type == BCOND_CTR)
            tcg_gen_mov_tl(target, cpu_ctr);
        else
            tcg_gen_mov_tl(target, cpu_lr);
3529
    }
3530 3531
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
3532 3533 3534 3535 3536 3537 3538 3539 3540
    l1 = gen_new_label();
    if ((bo & 0x4) == 0) {
        /* Decrement and test CTR */
        TCGv temp = tcg_temp_new(TCG_TYPE_TL);
        if (unlikely(type == BCOND_CTR)) {
            GEN_EXCP_INVAL(ctx);
            return;
        }
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3541
#if defined(TARGET_PPC64)
3542 3543 3544
        if (!ctx->sf_mode)
            tcg_gen_ext32u_tl(temp, cpu_ctr);
        else
3545
#endif
3546 3547 3548 3549 3550
            tcg_gen_mov_tl(temp, cpu_ctr);
        if (bo & 0x2) {
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
        } else {
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3551
        }
3552 3553 3554 3555 3556 3557 3558
    }
    if ((bo & 0x10) == 0) {
        /* Test CR */
        uint32_t bi = BI(ctx->opcode);
        uint32_t mask = 1 << (3 - (bi & 0x03));
        TCGv temp = tcg_temp_new(TCG_TYPE_I32);

3559
        if (bo & 0x8) {
3560 3561
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3562
        } else {
3563 3564
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3565 3566
        }
    }
3567
    if (type == BCOND_IM) {
3568 3569 3570 3571 3572 3573
        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
        if (likely(AA(ctx->opcode) == 0)) {
            gen_goto_tb(ctx, 0, ctx->nip + li - 4);
        } else {
            gen_goto_tb(ctx, 0, li);
        }
B
bellard 已提交
3574
        gen_set_label(l1);
3575
        gen_goto_tb(ctx, 1, ctx->nip);
3576
    } else {
3577
#if defined(TARGET_PPC64)
3578 3579 3580 3581 3582 3583 3584 3585 3586 3587
        if (!(ctx->sf_mode))
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
        else
#endif
            tcg_gen_andi_tl(cpu_nip, target, ~3);
        tcg_gen_exit_tb(0);
        gen_set_label(l1);
#if defined(TARGET_PPC64)
        if (!(ctx->sf_mode))
            tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
3588 3589
        else
#endif
3590
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
B
bellard 已提交
3591
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3592
    }
3593 3594 3595
}

GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3596
{
3597 3598 3599 3600
    gen_bcond(ctx, BCOND_IM);
}

GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3601
{
3602 3603 3604 3605
    gen_bcond(ctx, BCOND_CTR);
}

GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3606
{
3607 3608
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3609 3610

/***                      Condition register logical                       ***/
3611 3612
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)                   \
B
bellard 已提交
3613
{                                                                             \
3614 3615
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
3616
    TCGv t0, t1;                                                              \
3617
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
3618
    t0 = tcg_temp_new(TCG_TYPE_I32);                                          \
3619
    if (sh > 0)                                                               \
3620
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3621
    else if (sh < 0)                                                          \
3622
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3623
    else                                                                      \
3624 3625
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
    t1 = tcg_temp_new(TCG_TYPE_I32);                                          \
3626 3627
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
3628
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3629
    else if (sh < 0)                                                          \
3630
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3631
    else                                                                      \
3632 3633
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
    tcg_op(t0, t0, t1);                                                       \
3634
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3635 3636 3637 3638 3639
    tcg_gen_andi_i32(t0, t0, bitmask);                                        \
    tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask);          \
    tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1);                  \
    tcg_temp_free(t0);                                                        \
    tcg_temp_free(t1);                                                        \
B
bellard 已提交
3640 3641 3642
}

/* crand */
3643
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
B
bellard 已提交
3644
/* crandc */
3645
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
B
bellard 已提交
3646
/* creqv */
3647
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
B
bellard 已提交
3648
/* crnand */
3649
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
B
bellard 已提交
3650
/* crnor */
3651
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
B
bellard 已提交
3652
/* cror */
3653
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
B
bellard 已提交
3654
/* crorc */
3655
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
B
bellard 已提交
3656
/* crxor */
3657
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
B
bellard 已提交
3658 3659 3660
/* mcrf */
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
{
A
aurel32 已提交
3661
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
B
bellard 已提交
3662 3663 3664 3665
}

/***                           System linkage                              ***/
/* rfi (supervisor only) */
3666
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
B
bellard 已提交
3667
{
3668
#if defined(CONFIG_USER_ONLY)
3669
    GEN_EXCP_PRIVOPC(ctx);
3670 3671
#else
    /* Restore CPU state */
3672
    if (unlikely(!ctx->supervisor)) {
3673
        GEN_EXCP_PRIVOPC(ctx);
3674
        return;
3675
    }
3676
    gen_op_rfi();
3677
    GEN_SYNC(ctx);
3678
#endif
B
bellard 已提交
3679 3680
}

J
j_mayer 已提交
3681
#if defined(TARGET_PPC64)
3682
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
J
j_mayer 已提交
3683 3684
{
#if defined(CONFIG_USER_ONLY)
3685
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3686 3687 3688
#else
    /* Restore CPU state */
    if (unlikely(!ctx->supervisor)) {
3689
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3690 3691
        return;
    }
3692
    gen_op_rfid();
3693
    GEN_SYNC(ctx);
J
j_mayer 已提交
3694 3695 3696
#endif
}

J
j_mayer 已提交
3697
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712
{
#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 已提交
3713
/* sc */
3714 3715 3716 3717 3718
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
3719
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
B
bellard 已提交
3720
{
3721 3722 3723
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
3724
    GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3725 3726 3727 3728
}

/***                                Trap                                   ***/
/* tw */
3729
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
B
bellard 已提交
3730
{
A
aurel32 已提交
3731 3732
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3733
    /* Update the nip since this might generate a trap exception */
3734
    gen_update_nip(ctx, ctx->nip);
3735
    gen_op_tw(TO(ctx->opcode));
B
bellard 已提交
3736 3737 3738 3739 3740
}

/* twi */
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
A
aurel32 已提交
3741
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
3742
    tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3743 3744
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3745
    gen_op_tw(TO(ctx->opcode));
B
bellard 已提交
3746 3747
}

3748 3749 3750 3751
#if defined(TARGET_PPC64)
/* td */
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
{
A
aurel32 已提交
3752 3753
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3754 3755 3756 3757 3758 3759 3760 3761
    /* 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 已提交
3762
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
A
aurel32 已提交
3763
    tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3764 3765 3766 3767 3768 3769
    /* 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 已提交
3770 3771 3772 3773
/***                          Processor control                            ***/
/* mcrxr */
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
{
A
aurel32 已提交
3774 3775
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3776
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
B
bellard 已提交
3777 3778 3779
}

/* mfcr */
3780
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
B
bellard 已提交
3781
{
3782
    uint32_t crm, crn;
3783

3784 3785 3786 3787
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
        if (likely((crm ^ (crm - 1)) == 0)) {
            crn = ffs(crm);
3788
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
3789
        }
3790
    } else {
3791
        tcg_gen_helper_1_0(helper_load_cr, cpu_gpr[rD(ctx->opcode)]);
3792
    }
B
bellard 已提交
3793 3794 3795 3796 3797
}

/* mfmsr */
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
{
3798
#if defined(CONFIG_USER_ONLY)
3799
    GEN_EXCP_PRIVREG(ctx);
3800
#else
3801
    if (unlikely(!ctx->supervisor)) {
3802
        GEN_EXCP_PRIVREG(ctx);
3803
        return;
3804
    }
A
aurel32 已提交
3805
    gen_op_load_msr();
A
aurel32 已提交
3806
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3807
#endif
B
bellard 已提交
3808 3809
}

J
j_mayer 已提交
3810
#if 1
3811
#define SPR_NOACCESS ((void *)(-1UL))
3812 3813 3814 3815 3816 3817 3818 3819 3820
#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 已提交
3821
/* mfspr */
3822
static always_inline void gen_op_mfspr (DisasContext *ctx)
B
bellard 已提交
3823
{
3824
    void (*read_cb)(void *opaque, int sprn);
B
bellard 已提交
3825 3826
    uint32_t sprn = SPR(ctx->opcode);

3827
#if !defined(CONFIG_USER_ONLY)
3828 3829
    if (ctx->supervisor == 2)
        read_cb = ctx->spr_cb[sprn].hea_read;
3830
    else if (ctx->supervisor)
3831 3832
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3833
#endif
3834
        read_cb = ctx->spr_cb[sprn].uea_read;
3835 3836
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
3837
            (*read_cb)(ctx, sprn);
A
aurel32 已提交
3838
            tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3839 3840
        } else {
            /* Privilege exception */
3841 3842 3843 3844 3845 3846
            /* 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) {
3847
                    fprintf(logfile, "Trying to read privileged spr %d %03x at "
J
j_mayer 已提交
3848
                            ADDRX "\n", sprn, sprn, ctx->nip);
3849
                }
J
j_mayer 已提交
3850 3851
                printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
                       sprn, sprn, ctx->nip);
3852
            }
3853
            GEN_EXCP_PRIVREG(ctx);
B
bellard 已提交
3854
        }
3855 3856
    } else {
        /* Not defined */
J
j_mayer 已提交
3857
        if (loglevel != 0) {
J
j_mayer 已提交
3858 3859
            fprintf(logfile, "Trying to read invalid spr %d %03x at "
                    ADDRX "\n", sprn, sprn, ctx->nip);
3860
        }
J
j_mayer 已提交
3861 3862
        printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
               sprn, sprn, ctx->nip);
3863 3864
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3865 3866 3867
    }
}

3868
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
B
bellard 已提交
3869
{
3870
    gen_op_mfspr(ctx);
3871
}
3872 3873

/* mftb */
3874
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3875 3876
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3877 3878 3879
}

/* mtcrf */
3880
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
B
bellard 已提交
3881
{
3882
    uint32_t crm, crn;
3883

3884 3885 3886
    crm = CRM(ctx->opcode);
    if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
        crn = ffs(crm);
3887 3888
        tcg_gen_shri_i32(cpu_crf[7 - crn], cpu_gpr[rS(ctx->opcode)], crn * 4);
        tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3889
    } else {
3890 3891 3892
        TCGv t0 = tcg_const_tl(crm);
        tcg_gen_helper_0_2(helper_store_cr, cpu_gpr[rS(ctx->opcode)], t0);
        tcg_temp_free(t0);
3893
    }
B
bellard 已提交
3894 3895 3896
}

/* mtmsr */
J
j_mayer 已提交
3897
#if defined(TARGET_PPC64)
3898
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
J
j_mayer 已提交
3899 3900
{
#if defined(CONFIG_USER_ONLY)
3901
    GEN_EXCP_PRIVREG(ctx);
J
j_mayer 已提交
3902 3903
#else
    if (unlikely(!ctx->supervisor)) {
3904
        GEN_EXCP_PRIVREG(ctx);
J
j_mayer 已提交
3905 3906
        return;
    }
A
aurel32 已提交
3907
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3908 3909 3910 3911
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
        gen_op_update_riee();
    } else {
3912 3913 3914 3915
        /* 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
         */
3916
        gen_update_nip(ctx, ctx->nip);
A
aurel32 已提交
3917
        gen_op_store_msr();
3918 3919
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
3920
        ctx->exception = POWERPC_EXCP_STOP;
3921
    }
J
j_mayer 已提交
3922 3923 3924 3925
#endif
}
#endif

B
bellard 已提交
3926 3927
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
{
3928
#if defined(CONFIG_USER_ONLY)
3929
    GEN_EXCP_PRIVREG(ctx);
3930
#else
3931
    if (unlikely(!ctx->supervisor)) {
3932
        GEN_EXCP_PRIVREG(ctx);
3933
        return;
3934
    }
A
aurel32 已提交
3935
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3936 3937 3938 3939
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
        gen_op_update_riee();
    } else {
3940 3941 3942 3943
        /* 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
         */
3944
        gen_update_nip(ctx, ctx->nip);
3945
#if defined(TARGET_PPC64)
3946
        if (!ctx->sf_mode)
A
aurel32 已提交
3947
            gen_op_store_msr_32();
3948
        else
3949
#endif
A
aurel32 已提交
3950
            gen_op_store_msr();
3951 3952
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsrd is not always defined as context-synchronizing */
3953
        ctx->exception = POWERPC_EXCP_STOP;
3954
    }
3955
#endif
B
bellard 已提交
3956 3957 3958 3959 3960
}

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

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

/***                         Cache management                              ***/
/* dcbf */
4001
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
B
bellard 已提交
4002
{
J
j_mayer 已提交
4003
    /* XXX: specification says this is treated as a load by the MMU */
4004 4005 4006 4007
    TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_reg_index(t0, ctx);
    gen_qemu_ld8u(t0, t0, ctx->mem_idx);
    tcg_temp_free(t0);
B
bellard 已提交
4008 4009 4010
}

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

/* dcdst */
4033
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
B
bellard 已提交
4034
{
4035
    /* XXX: specification say this is treated as a load by the MMU */
4036 4037 4038 4039
    TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_reg_index(t0, ctx);
    gen_qemu_ld8u(t0, t0, ctx->mem_idx);
    tcg_temp_free(t0);
B
bellard 已提交
4040 4041 4042
}

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

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

/* dcbz */
4061
#define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
4062 4063
static GenOpFunc *gen_op_dcbz[4][NB_MEM_FUNCS] = {
    /* 32 bytes cache line size */
4064
    {
4065 4066 4067 4068 4069 4070 4071 4072 4073
#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),
4074
    },
4075
    /* 64 bytes cache line size */
4076
    {
4077 4078 4079 4080 4081 4082 4083 4084 4085
#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),
4086
    },
4087
    /* 128 bytes cache line size */
4088
    {
4089 4090 4091 4092 4093 4094 4095 4096 4097
#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),
4098
    },
4099
    /* tunable cache line size */
4100
    {
4101 4102 4103 4104 4105 4106 4107 4108 4109
#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),
4110
    },
4111
};
4112

4113 4114
static always_inline void handler_dcbz (DisasContext *ctx,
                                        int dcache_line_size)
4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135
{
    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 已提交
4136
{
4137
    gen_addr_reg_index(cpu_T[0], ctx);
4138 4139 4140 4141
    handler_dcbz(ctx, ctx->dcache_line_size);
    gen_op_check_reservation();
}

4142
GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
4143
{
4144
    gen_addr_reg_index(cpu_T[0], ctx);
4145 4146 4147 4148
    if (ctx->opcode & 0x00200000)
        handler_dcbz(ctx, ctx->dcache_line_size);
    else
        handler_dcbz(ctx, -1);
B
bellard 已提交
4149
    gen_op_check_reservation();
B
bellard 已提交
4150 4151 4152
}

/* icbi */
4153
#define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
4154 4155 4156 4157 4158 4159 4160 4161 4162 4163
#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),
4164
};
4165

4166
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
B
bellard 已提交
4167
{
4168 4169
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
4170
    gen_addr_reg_index(cpu_T[0], ctx);
4171
    op_icbi();
B
bellard 已提交
4172 4173 4174 4175
}

/* Optional: */
/* dcba */
4176
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
B
bellard 已提交
4177
{
4178 4179 4180 4181
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
4182 4183 4184 4185 4186 4187 4188
}

/***                    Segment register manipulation                      ***/
/* Supervisor only: */
/* mfsr */
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
{
4189
#if defined(CONFIG_USER_ONLY)
4190
    GEN_EXCP_PRIVREG(ctx);
4191
#else
4192
    if (unlikely(!ctx->supervisor)) {
4193
        GEN_EXCP_PRIVREG(ctx);
4194
        return;
4195
    }
4196
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
4197
    gen_op_load_sr();
A
aurel32 已提交
4198
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4199
#endif
B
bellard 已提交
4200 4201 4202
}

/* mfsrin */
4203
GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
B
bellard 已提交
4204
{
4205
#if defined(CONFIG_USER_ONLY)
4206
    GEN_EXCP_PRIVREG(ctx);
4207
#else
4208
    if (unlikely(!ctx->supervisor)) {
4209
        GEN_EXCP_PRIVREG(ctx);
4210
        return;
4211
    }
A
aurel32 已提交
4212
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4213 4214
    gen_op_srli_T1(28);
    gen_op_load_sr();
A
aurel32 已提交
4215
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4216
#endif
B
bellard 已提交
4217 4218 4219
}

/* mtsr */
B
bellard 已提交
4220
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
B
bellard 已提交
4221
{
4222
#if defined(CONFIG_USER_ONLY)
4223
    GEN_EXCP_PRIVREG(ctx);
4224
#else
4225
    if (unlikely(!ctx->supervisor)) {
4226
        GEN_EXCP_PRIVREG(ctx);
4227
        return;
4228
    }
A
aurel32 已提交
4229
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4230
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
4231
    gen_op_store_sr();
4232
#endif
B
bellard 已提交
4233 4234 4235
}

/* mtsrin */
4236
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
B
bellard 已提交
4237
{
4238
#if defined(CONFIG_USER_ONLY)
4239
    GEN_EXCP_PRIVREG(ctx);
4240
#else
4241
    if (unlikely(!ctx->supervisor)) {
4242
        GEN_EXCP_PRIVREG(ctx);
4243
        return;
4244
    }
A
aurel32 已提交
4245 4246
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4247 4248
    gen_op_srli_T1(28);
    gen_op_store_sr();
4249
#endif
B
bellard 已提交
4250 4251
}

4252 4253 4254
#if defined(TARGET_PPC64)
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
/* mfsr */
4255
GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
4256 4257 4258 4259 4260 4261 4262 4263
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
4264
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
4265
    gen_op_load_slb();
A
aurel32 已提交
4266
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4267 4268 4269 4270
#endif
}

/* mfsrin */
4271 4272
GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
             PPC_SEGMENT_64B)
4273 4274 4275 4276 4277 4278 4279 4280
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
A
aurel32 已提交
4281
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4282 4283
    gen_op_srli_T1(28);
    gen_op_load_slb();
A
aurel32 已提交
4284
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4285 4286 4287 4288
#endif
}

/* mtsr */
4289
GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
4290 4291 4292 4293 4294 4295 4296 4297
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
A
aurel32 已提交
4298
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4299
    tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
4300 4301 4302 4303 4304
    gen_op_store_slb();
#endif
}

/* mtsrin */
4305 4306
GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
             PPC_SEGMENT_64B)
4307 4308 4309 4310 4311 4312 4313 4314
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
A
aurel32 已提交
4315 4316
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4317 4318 4319 4320 4321 4322
    gen_op_srli_T1(28);
    gen_op_store_slb();
#endif
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
4323 4324 4325
/***                      Lookaside buffer management                      ***/
/* Optional & supervisor only: */
/* tlbia */
4326
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
B
bellard 已提交
4327
{
4328
#if defined(CONFIG_USER_ONLY)
4329
    GEN_EXCP_PRIVOPC(ctx);
4330
#else
4331
    if (unlikely(!ctx->supervisor)) {
4332
        GEN_EXCP_PRIVOPC(ctx);
4333
        return;
4334 4335 4336
    }
    gen_op_tlbia();
#endif
B
bellard 已提交
4337 4338 4339
}

/* tlbie */
4340
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
B
bellard 已提交
4341
{
4342
#if defined(CONFIG_USER_ONLY)
4343
    GEN_EXCP_PRIVOPC(ctx);
4344
#else
4345
    if (unlikely(!ctx->supervisor)) {
4346
        GEN_EXCP_PRIVOPC(ctx);
4347
        return;
4348
    }
A
aurel32 已提交
4349
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4350 4351 4352 4353 4354 4355
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_tlbie_64();
    else
#endif
        gen_op_tlbie();
4356
#endif
B
bellard 已提交
4357 4358 4359
}

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

J
j_mayer 已提交
4376 4377 4378 4379 4380
#if defined(TARGET_PPC64)
/* slbia */
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
{
#if defined(CONFIG_USER_ONLY)
4381
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
4382 4383
#else
    if (unlikely(!ctx->supervisor)) {
4384
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
4385 4386 4387 4388 4389 4390 4391 4392 4393 4394
        return;
    }
    gen_op_slbia();
#endif
}

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

B
bellard 已提交
4407 4408
/***                              External control                         ***/
/* Optional: */
4409 4410
#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
4411 4412
static GenOpFunc *gen_op_eciwx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(eciwx),
4413
};
4414 4415
static GenOpFunc *gen_op_ecowx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(ecowx),
4416
};
4417

4418
/* eciwx */
B
bellard 已提交
4419 4420
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
{
4421
    /* Should check EAR[E] & alignment ! */
4422
    gen_addr_reg_index(cpu_T[0], ctx);
4423
    op_eciwx();
A
aurel32 已提交
4424
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4425 4426 4427 4428 4429 4430
}

/* ecowx */
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
{
    /* Should check EAR[E] & alignment ! */
4431
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
4432
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4433 4434 4435 4436 4437 4438 4439
    op_ecowx();
}

/* PowerPC 601 specific instructions */
/* abs - abs. */
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
{
A
aurel32 已提交
4440
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4441
    gen_op_POWER_abs();
A
aurel32 已提交
4442
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4443
    if (unlikely(Rc(ctx->opcode) != 0))
4444
        gen_set_Rc0(ctx, cpu_T[0]);
4445 4446 4447 4448 4449
}

/* abso - abso. */
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
{
A
aurel32 已提交
4450
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4451
    gen_op_POWER_abso();
A
aurel32 已提交
4452
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4453
    if (unlikely(Rc(ctx->opcode) != 0))
4454
        gen_set_Rc0(ctx, cpu_T[0]);
4455 4456 4457
}

/* clcs */
4458
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
4459
{
A
aurel32 已提交
4460
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4461
    gen_op_POWER_clcs();
4462
    /* Rc=1 sets CR0 to an undefined state */
A
aurel32 已提交
4463
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4464 4465 4466 4467 4468
}

/* div - div. */
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4469 4470
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4471
    gen_op_POWER_div();
A
aurel32 已提交
4472
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4473
    if (unlikely(Rc(ctx->opcode) != 0))
4474
        gen_set_Rc0(ctx, cpu_T[0]);
4475 4476 4477 4478 4479
}

/* divo - divo. */
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4480 4481
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4482
    gen_op_POWER_divo();
A
aurel32 已提交
4483
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4484
    if (unlikely(Rc(ctx->opcode) != 0))
4485
        gen_set_Rc0(ctx, cpu_T[0]);
4486 4487 4488 4489 4490
}

/* divs - divs. */
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4491 4492
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4493
    gen_op_POWER_divs();
A
aurel32 已提交
4494
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4495
    if (unlikely(Rc(ctx->opcode) != 0))
4496
        gen_set_Rc0(ctx, cpu_T[0]);
4497 4498 4499 4500 4501
}

/* divso - divso. */
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4502 4503
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4504
    gen_op_POWER_divso();
A
aurel32 已提交
4505
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4506
    if (unlikely(Rc(ctx->opcode) != 0))
4507
        gen_set_Rc0(ctx, cpu_T[0]);
4508 4509 4510 4511 4512
}

/* doz - doz. */
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4513 4514
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4515
    gen_op_POWER_doz();
A
aurel32 已提交
4516
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4517
    if (unlikely(Rc(ctx->opcode) != 0))
4518
        gen_set_Rc0(ctx, cpu_T[0]);
4519 4520 4521 4522 4523
}

/* dozo - dozo. */
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4524 4525
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4526
    gen_op_POWER_dozo();
A
aurel32 已提交
4527
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4528
    if (unlikely(Rc(ctx->opcode) != 0))
4529
        gen_set_Rc0(ctx, cpu_T[0]);
4530 4531 4532 4533 4534
}

/* dozi */
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4535
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4536
    tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
4537
    gen_op_POWER_doz();
A
aurel32 已提交
4538
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4539 4540
}

4541 4542 4543
/* 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
 */
4544
#define op_POWER_lscbx(start, ra, rb)                                         \
4545
(*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559
#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),
4560 4561 4562 4563 4564 4565 4566 4567
};

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

4568
    gen_addr_reg_index(cpu_T[0], ctx);
4569 4570 4571 4572
    if (ra == 0) {
        ra = rb;
    }
    /* NIP cannot be restored if the memory exception comes from an helper */
4573
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4574 4575 4576
    tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F);
    tcg_gen_shri_tl(cpu_T[2], cpu_xer, XER_CMP);
    tcg_gen_andi_tl(cpu_T[2], cpu_T[2], 0xFF);
4577
    op_POWER_lscbx(rD(ctx->opcode), ra, rb);
A
aurel32 已提交
4578 4579
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
    tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]);
4580
    if (unlikely(Rc(ctx->opcode) != 0))
4581
        gen_set_Rc0(ctx, cpu_T[0]);
4582 4583 4584 4585 4586
}

/* maskg - maskg. */
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4587 4588
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4589
    gen_op_POWER_maskg();
A
aurel32 已提交
4590
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4591
    if (unlikely(Rc(ctx->opcode) != 0))
4592
        gen_set_Rc0(ctx, cpu_T[0]);
4593 4594 4595 4596 4597
}

/* maskir - maskir. */
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4598 4599 4600
    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)]);
4601
    gen_op_POWER_maskir();
A
aurel32 已提交
4602
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4603
    if (unlikely(Rc(ctx->opcode) != 0))
4604
        gen_set_Rc0(ctx, cpu_T[0]);
4605 4606 4607 4608 4609
}

/* mul - mul. */
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4610 4611
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4612
    gen_op_POWER_mul();
A
aurel32 已提交
4613
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4614
    if (unlikely(Rc(ctx->opcode) != 0))
4615
        gen_set_Rc0(ctx, cpu_T[0]);
4616 4617 4618 4619 4620
}

/* mulo - mulo. */
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4621 4622
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4623
    gen_op_POWER_mulo();
A
aurel32 已提交
4624
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4625
    if (unlikely(Rc(ctx->opcode) != 0))
4626
        gen_set_Rc0(ctx, cpu_T[0]);
4627 4628 4629 4630 4631
}

/* nabs - nabs. */
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4632
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4633
    gen_op_POWER_nabs();
A
aurel32 已提交
4634
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4635
    if (unlikely(Rc(ctx->opcode) != 0))
4636
        gen_set_Rc0(ctx, cpu_T[0]);
4637 4638 4639 4640 4641
}

/* nabso - nabso. */
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4642
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4643
    gen_op_POWER_nabso();
A
aurel32 已提交
4644
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4645
    if (unlikely(Rc(ctx->opcode) != 0))
4646
        gen_set_Rc0(ctx, cpu_T[0]);
4647 4648 4649 4650 4651 4652 4653 4654 4655
}

/* 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 已提交
4656 4657 4658
    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)]);
4659
    gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
A
aurel32 已提交
4660
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4661
    if (unlikely(Rc(ctx->opcode) != 0))
4662
        gen_set_Rc0(ctx, cpu_T[0]);
4663 4664 4665 4666 4667
}

/* rrib - rrib. */
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4668 4669 4670
    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)]);
4671
    gen_op_POWER_rrib();
A
aurel32 已提交
4672
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4673
    if (unlikely(Rc(ctx->opcode) != 0))
4674
        gen_set_Rc0(ctx, cpu_T[0]);
4675 4676 4677 4678 4679
}

/* sle - sle. */
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4680 4681
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4682
    gen_op_POWER_sle();
A
aurel32 已提交
4683
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4684
    if (unlikely(Rc(ctx->opcode) != 0))
4685
        gen_set_Rc0(ctx, cpu_T[0]);
4686 4687 4688 4689 4690
}

/* sleq - sleq. */
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4691 4692
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4693
    gen_op_POWER_sleq();
A
aurel32 已提交
4694
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4695
    if (unlikely(Rc(ctx->opcode) != 0))
4696
        gen_set_Rc0(ctx, cpu_T[0]);
4697 4698 4699 4700 4701
}

/* sliq - sliq. */
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4702
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4703
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4704
    gen_op_POWER_sle();
A
aurel32 已提交
4705
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4706
    if (unlikely(Rc(ctx->opcode) != 0))
4707
        gen_set_Rc0(ctx, cpu_T[0]);
4708 4709 4710 4711 4712
}

/* slliq - slliq. */
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4713
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4714
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4715
    gen_op_POWER_sleq();
A
aurel32 已提交
4716
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4717
    if (unlikely(Rc(ctx->opcode) != 0))
4718
        gen_set_Rc0(ctx, cpu_T[0]);
4719 4720 4721 4722 4723
}

/* sllq - sllq. */
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4724 4725
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4726
    gen_op_POWER_sllq();
A
aurel32 已提交
4727
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4728
    if (unlikely(Rc(ctx->opcode) != 0))
4729
        gen_set_Rc0(ctx, cpu_T[0]);
4730 4731 4732 4733 4734
}

/* slq - slq. */
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4735 4736
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4737
    gen_op_POWER_slq();
A
aurel32 已提交
4738
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4739
    if (unlikely(Rc(ctx->opcode) != 0))
4740
        gen_set_Rc0(ctx, cpu_T[0]);
4741 4742
}

4743
/* sraiq - sraiq. */
4744 4745
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4746
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4747
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4748
    gen_op_POWER_sraq();
A
aurel32 已提交
4749
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4750
    if (unlikely(Rc(ctx->opcode) != 0))
4751
        gen_set_Rc0(ctx, cpu_T[0]);
4752 4753 4754 4755 4756
}

/* sraq - sraq. */
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4757 4758
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4759
    gen_op_POWER_sraq();
A
aurel32 已提交
4760
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4761
    if (unlikely(Rc(ctx->opcode) != 0))
4762
        gen_set_Rc0(ctx, cpu_T[0]);
4763 4764 4765 4766 4767
}

/* sre - sre. */
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4768 4769
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4770
    gen_op_POWER_sre();
A
aurel32 已提交
4771
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4772
    if (unlikely(Rc(ctx->opcode) != 0))
4773
        gen_set_Rc0(ctx, cpu_T[0]);
4774 4775 4776 4777 4778
}

/* srea - srea. */
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4779 4780
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4781
    gen_op_POWER_srea();
A
aurel32 已提交
4782
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4783
    if (unlikely(Rc(ctx->opcode) != 0))
4784
        gen_set_Rc0(ctx, cpu_T[0]);
4785 4786 4787 4788 4789
}

/* sreq */
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4790 4791
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4792
    gen_op_POWER_sreq();
A
aurel32 已提交
4793
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4794
    if (unlikely(Rc(ctx->opcode) != 0))
4795
        gen_set_Rc0(ctx, cpu_T[0]);
4796 4797 4798 4799 4800
}

/* sriq */
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4801
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4802
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4803
    gen_op_POWER_srq();
A
aurel32 已提交
4804
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4805
    if (unlikely(Rc(ctx->opcode) != 0))
4806
        gen_set_Rc0(ctx, cpu_T[0]);
4807 4808 4809 4810 4811
}

/* srliq */
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4812 4813
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4814
    tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4815
    gen_op_POWER_srlq();
A
aurel32 已提交
4816
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4817
    if (unlikely(Rc(ctx->opcode) != 0))
4818
        gen_set_Rc0(ctx, cpu_T[0]);
4819 4820 4821 4822 4823
}

/* srlq */
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4824 4825
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4826
    gen_op_POWER_srlq();
A
aurel32 已提交
4827
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4828
    if (unlikely(Rc(ctx->opcode) != 0))
4829
        gen_set_Rc0(ctx, cpu_T[0]);
4830 4831 4832 4833 4834
}

/* srq */
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
{
A
aurel32 已提交
4835 4836
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4837
    gen_op_POWER_srq();
A
aurel32 已提交
4838
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4839
    if (unlikely(Rc(ctx->opcode) != 0))
4840
        gen_set_Rc0(ctx, cpu_T[0]);
4841 4842 4843 4844 4845 4846 4847
}

/* PowerPC 602 specific instructions */
/* dsa  */
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4848
    GEN_EXCP_INVAL(ctx);
4849 4850 4851 4852 4853 4854
}

/* esa */
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4855
    GEN_EXCP_INVAL(ctx);
4856 4857 4858 4859 4860 4861
}

/* mfrom */
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
{
#if defined(CONFIG_USER_ONLY)
4862
    GEN_EXCP_PRIVOPC(ctx);
4863 4864
#else
    if (unlikely(!ctx->supervisor)) {
4865
        GEN_EXCP_PRIVOPC(ctx);
4866 4867
        return;
    }
A
aurel32 已提交
4868
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4869
    gen_op_602_mfrom();
A
aurel32 已提交
4870
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4871 4872 4873 4874 4875
#endif
}

/* 602 - 603 - G2 TLB management */
/* tlbld */
4876
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
4877 4878
{
#if defined(CONFIG_USER_ONLY)
4879
    GEN_EXCP_PRIVOPC(ctx);
4880 4881
#else
    if (unlikely(!ctx->supervisor)) {
4882
        GEN_EXCP_PRIVOPC(ctx);
4883 4884
        return;
    }
A
aurel32 已提交
4885
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4886 4887 4888 4889 4890
    gen_op_6xx_tlbld();
#endif
}

/* tlbli */
4891
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
4892 4893
{
#if defined(CONFIG_USER_ONLY)
4894
    GEN_EXCP_PRIVOPC(ctx);
4895 4896
#else
    if (unlikely(!ctx->supervisor)) {
4897
        GEN_EXCP_PRIVOPC(ctx);
4898 4899
        return;
    }
A
aurel32 已提交
4900
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4901 4902 4903 4904
    gen_op_6xx_tlbli();
#endif
}

4905 4906
/* 74xx TLB management */
/* tlbld */
4907
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
4908 4909 4910 4911 4912 4913 4914 4915
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
A
aurel32 已提交
4916
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4917 4918 4919 4920 4921
    gen_op_74xx_tlbld();
#endif
}

/* tlbli */
4922
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
4923 4924 4925 4926 4927 4928 4929 4930
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
A
aurel32 已提交
4931
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4932 4933 4934 4935
    gen_op_74xx_tlbli();
#endif
}

4936 4937 4938 4939 4940 4941 4942 4943 4944 4945
/* 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 已提交
4946
    /* Cache line invalidate: privileged and treated as no-op */
4947
#if defined(CONFIG_USER_ONLY)
4948
    GEN_EXCP_PRIVOPC(ctx);
4949 4950
#else
    if (unlikely(!ctx->supervisor)) {
4951
        GEN_EXCP_PRIVOPC(ctx);
4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965
        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)
4966
    GEN_EXCP_PRIVOPC(ctx);
4967 4968
#else
    if (unlikely(!ctx->supervisor)) {
4969
        GEN_EXCP_PRIVOPC(ctx);
4970 4971 4972 4973 4974
        return;
    }
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);

4975
    gen_addr_reg_index(cpu_T[0], ctx);
4976
    gen_op_POWER_mfsri();
A
aurel32 已提交
4977
    tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
4978
    if (ra != 0 && ra != rd)
A
aurel32 已提交
4979
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
4980 4981 4982 4983 4984 4985
#endif
}

GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
4986
    GEN_EXCP_PRIVOPC(ctx);
4987 4988
#else
    if (unlikely(!ctx->supervisor)) {
4989
        GEN_EXCP_PRIVOPC(ctx);
4990 4991
        return;
    }
4992
    gen_addr_reg_index(cpu_T[0], ctx);
4993
    gen_op_POWER_rac();
A
aurel32 已提交
4994
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4995 4996 4997 4998 4999 5000
#endif
}

GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
5001
    GEN_EXCP_PRIVOPC(ctx);
5002 5003
#else
    if (unlikely(!ctx->supervisor)) {
5004
        GEN_EXCP_PRIVOPC(ctx);
5005 5006 5007
        return;
    }
    gen_op_POWER_rfsvc();
5008
    GEN_SYNC(ctx);
5009 5010 5011 5012 5013 5014 5015
#endif
}

/* svc is not implemented for now */

/* POWER2 specific instructions */
/* Quad manipulation (load/store two floats at a time) */
5016
/* Original POWER2 is 32 bits only, define 64 bits ops as 32 bits ones */
5017 5018
#define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
#define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036
#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),
5037
};
5038 5039
static GenOpFunc *gen_op_POWER2_stfq[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(POWER2_stfq),
5040 5041 5042 5043 5044 5045
};

/* lfq */
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
5046
    gen_update_nip(ctx, ctx->nip - 4);
5047
    gen_addr_imm_index(cpu_T[0], ctx, 0);
5048
    op_POWER2_lfq();
A
aurel32 已提交
5049 5050
    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]);
5051 5052 5053 5054 5055 5056 5057 5058
}

/* 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 */
5059
    gen_update_nip(ctx, ctx->nip - 4);
5060
    gen_addr_imm_index(cpu_T[0], ctx, 0);
5061
    op_POWER2_lfq();
A
aurel32 已提交
5062 5063
    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]);
5064
    if (ra != 0)
A
aurel32 已提交
5065
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
5066 5067 5068 5069 5070 5071 5072 5073
}

/* 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 */
5074
    gen_update_nip(ctx, ctx->nip - 4);
5075
    gen_addr_reg_index(cpu_T[0], ctx);
5076
    op_POWER2_lfq();
A
aurel32 已提交
5077 5078
    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]);
5079
    if (ra != 0)
A
aurel32 已提交
5080
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
5081 5082 5083 5084 5085 5086
}

/* lfqx */
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
5087
    gen_update_nip(ctx, ctx->nip - 4);
5088
    gen_addr_reg_index(cpu_T[0], ctx);
5089
    op_POWER2_lfq();
A
aurel32 已提交
5090 5091
    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]);
5092 5093 5094 5095 5096 5097
}

/* stfq */
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
5098
    gen_update_nip(ctx, ctx->nip - 4);
5099
    gen_addr_imm_index(cpu_T[0], ctx, 0);
A
aurel32 已提交
5100 5101
    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]);
5102 5103 5104 5105 5106 5107 5108 5109 5110
    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 */
5111
    gen_update_nip(ctx, ctx->nip - 4);
5112
    gen_addr_imm_index(cpu_T[0], ctx, 0);
A
aurel32 已提交
5113 5114
    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]);
5115 5116
    op_POWER2_stfq();
    if (ra != 0)
A
aurel32 已提交
5117
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
5118 5119 5120 5121 5122 5123 5124 5125
}

/* 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 */
5126
    gen_update_nip(ctx, ctx->nip - 4);
5127
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
5128 5129
    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]);
5130 5131
    op_POWER2_stfq();
    if (ra != 0)
A
aurel32 已提交
5132
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
5133 5134 5135 5136 5137 5138
}

/* stfqx */
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
5139
    gen_update_nip(ctx, ctx->nip - 4);
5140
    gen_addr_reg_index(cpu_T[0], ctx);
A
aurel32 已提交
5141 5142
    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]);
5143 5144 5145 5146
    op_POWER2_stfq();
}

/* BookE specific instructions */
5147
/* XXX: not implemented on 440 ? */
5148
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
5149 5150
{
    /* XXX: TODO */
5151
    GEN_EXCP_INVAL(ctx);
5152 5153
}

5154
/* XXX: not implemented on 440 ? */
5155
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
5156 5157
{
#if defined(CONFIG_USER_ONLY)
5158
    GEN_EXCP_PRIVOPC(ctx);
5159 5160
#else
    if (unlikely(!ctx->supervisor)) {
5161
        GEN_EXCP_PRIVOPC(ctx);
5162 5163
        return;
    }
5164
    gen_addr_reg_index(cpu_T[0], ctx);
5165
    /* Use the same micro-ops as for tlbie */
5166 5167 5168 5169 5170 5171
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_tlbie_64();
    else
#endif
        gen_op_tlbie();
5172 5173 5174 5175
#endif
}

/* All 405 MAC instructions are translated here */
5176 5177 5178
static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
                                                int opc2, int opc3,
                                                int ra, int rb, int rt, int Rc)
5179
{
5180 5181 5182 5183 5184
    TCGv t0, t1;

    t0 = tcg_temp_local_new(TCG_TYPE_TL);
    t1 = tcg_temp_local_new(TCG_TYPE_TL);

5185 5186 5187 5188 5189 5190 5191
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5192 5193 5194
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5195 5196 5197 5198 5199
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5200 5201 5202
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5203 5204 5205 5206 5207 5208 5209
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5210 5211 5212 5213
        tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
        tcg_gen_ext16s_tl(t0, t0);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5214 5215 5216 5217 5218
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5219 5220 5221 5222
        tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
        tcg_gen_ext16u_tl(t0, t0);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5223 5224 5225 5226 5227 5228 5229
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5230 5231
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5232 5233 5234 5235 5236
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5237 5238
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5239 5240 5241
        break;
    }
    if (opc2 & 0x04) {
5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265
        /* (n)multiply-and-accumulate (0x0C / 0x0E) */
        tcg_gen_mul_tl(t1, t0, t1);
        if (opc2 & 0x02) {
            /* nmultiply-and-accumulate (0x0E) */
            tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
        } else {
            /* multiply-and-accumulate (0x0C) */
            tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
        }

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

            if (opc3 & 0x10) {
                /* Start with XER OV disabled, the most likely case */
                tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
            }
            if (opc3 & 0x01) {
                /* Signed */
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
A
aurel32 已提交
5266
                if (opc3 & 0x02) {
5267 5268 5269 5270 5271 5272 5273
                    /* Saturate */
                    tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
                    tcg_gen_xori_tl(t0, t0, 0x7fffffff);
                }
            } else {
                /* Unsigned */
                tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
A
aurel32 已提交
5274
                if (opc3 & 0x02) {
5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287
                    /* Saturate */
                    tcg_gen_movi_tl(t0, UINT32_MAX);
                }
            }
            if (opc3 & 0x10) {
                /* Check overflow */
                tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
            }
            gen_set_label(l1);
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
        }
    } else {
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5288
    }
5289 5290
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5291 5292
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5293
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5294 5295 5296
    }
}

5297 5298
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)                  \
5299 5300 5301 5302 5303 5304
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
5305
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5306
/* macchwo   - macchwo.   */
5307
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5308
/* macchws   - macchws.   */
5309
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5310
/* macchwso  - macchwso.  */
5311
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5312
/* macchwsu  - macchwsu.  */
5313
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5314
/* macchwsuo - macchwsuo. */
5315
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5316
/* macchwu   - macchwu.   */
5317
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5318
/* macchwuo  - macchwuo.  */
5319
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5320
/* machhw    - machhw.    */
5321
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5322
/* machhwo   - machhwo.   */
5323
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5324
/* machhws   - machhws.   */
5325
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5326
/* machhwso  - machhwso.  */
5327
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5328
/* machhwsu  - machhwsu.  */
5329
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5330
/* machhwsuo - machhwsuo. */
5331
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5332
/* machhwu   - machhwu.   */
5333
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5334
/* machhwuo  - machhwuo.  */
5335
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5336
/* maclhw    - maclhw.    */
5337
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5338
/* maclhwo   - maclhwo.   */
5339
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5340
/* maclhws   - maclhws.   */
5341
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5342
/* maclhwso  - maclhwso.  */
5343
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5344
/* maclhwu   - maclhwu.   */
5345
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5346
/* maclhwuo  - maclhwuo.  */
5347
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5348
/* maclhwsu  - maclhwsu.  */
5349
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5350
/* maclhwsuo - maclhwsuo. */
5351
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5352
/* nmacchw   - nmacchw.   */
5353
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5354
/* nmacchwo  - nmacchwo.  */
5355
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5356
/* nmacchws  - nmacchws.  */
5357
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5358
/* nmacchwso - nmacchwso. */
5359
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5360
/* nmachhw   - nmachhw.   */
5361
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5362
/* nmachhwo  - nmachhwo.  */
5363
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5364
/* nmachhws  - nmachhws.  */
5365
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5366
/* nmachhwso - nmachhwso. */
5367
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5368
/* nmaclhw   - nmaclhw.   */
5369
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5370
/* nmaclhwo  - nmaclhwo.  */
5371
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5372
/* nmaclhws  - nmaclhws.  */
5373
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5374
/* nmaclhwso - nmaclhwso. */
5375
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5376 5377

/* mulchw  - mulchw.  */
5378
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5379
/* mulchwu - mulchwu. */
5380
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5381
/* mulhhw  - mulhhw.  */
5382
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5383
/* mulhhwu - mulhhwu. */
5384
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5385
/* mullhw  - mullhw.  */
5386
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5387
/* mullhwu - mullhwu. */
5388
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5389 5390

/* mfdcr */
5391
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
5392 5393
{
#if defined(CONFIG_USER_ONLY)
5394
    GEN_EXCP_PRIVREG(ctx);
5395 5396 5397 5398
#else
    uint32_t dcrn = SPR(ctx->opcode);

    if (unlikely(!ctx->supervisor)) {
5399
        GEN_EXCP_PRIVREG(ctx);
5400 5401
        return;
    }
5402
    tcg_gen_movi_tl(cpu_T[0], dcrn);
5403
    gen_op_load_dcr();
A
aurel32 已提交
5404
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5405 5406 5407 5408
#endif
}

/* mtdcr */
5409
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
5410 5411
{
#if defined(CONFIG_USER_ONLY)
5412
    GEN_EXCP_PRIVREG(ctx);
5413 5414 5415 5416
#else
    uint32_t dcrn = SPR(ctx->opcode);

    if (unlikely(!ctx->supervisor)) {
5417
        GEN_EXCP_PRIVREG(ctx);
5418 5419
        return;
    }
5420
    tcg_gen_movi_tl(cpu_T[0], dcrn);
A
aurel32 已提交
5421
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5422 5423 5424 5425 5426
    gen_op_store_dcr();
#endif
}

/* mfdcrx */
5427
/* XXX: not implemented on 440 ? */
5428
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
5429 5430
{
#if defined(CONFIG_USER_ONLY)
5431
    GEN_EXCP_PRIVREG(ctx);
5432 5433
#else
    if (unlikely(!ctx->supervisor)) {
5434
        GEN_EXCP_PRIVREG(ctx);
5435 5436
        return;
    }
A
aurel32 已提交
5437
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5438
    gen_op_load_dcr();
A
aurel32 已提交
5439
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5440
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5441 5442 5443 5444
#endif
}

/* mtdcrx */
5445
/* XXX: not implemented on 440 ? */
5446
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
5447 5448
{
#if defined(CONFIG_USER_ONLY)
5449
    GEN_EXCP_PRIVREG(ctx);
5450 5451
#else
    if (unlikely(!ctx->supervisor)) {
5452
        GEN_EXCP_PRIVREG(ctx);
5453 5454
        return;
    }
A
aurel32 已提交
5455 5456
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5457
    gen_op_store_dcr();
5458
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5459 5460 5461
#endif
}

5462 5463 5464
/* mfdcrux (PPC 460) : user-mode access to DCR */
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
{
A
aurel32 已提交
5465
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5466
    gen_op_load_dcr();
A
aurel32 已提交
5467
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5468 5469 5470 5471 5472 5473
    /* 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 已提交
5474 5475
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5476 5477 5478 5479
    gen_op_store_dcr();
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

5480 5481 5482 5483
/* dccci */
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
5484
    GEN_EXCP_PRIVOPC(ctx);
5485 5486
#else
    if (unlikely(!ctx->supervisor)) {
5487
        GEN_EXCP_PRIVOPC(ctx);
5488 5489 5490 5491 5492 5493 5494 5495 5496 5497
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
5498
    GEN_EXCP_PRIVOPC(ctx);
5499
#else
A
aurel32 已提交
5500
    TCGv EA, val;
5501
    if (unlikely(!ctx->supervisor)) {
5502
        GEN_EXCP_PRIVOPC(ctx);
5503 5504
        return;
    }
A
aurel32 已提交
5505 5506 5507 5508 5509 5510 5511
    EA = tcg_temp_new(TCG_TYPE_TL);
    gen_addr_reg_index(EA, ctx);
    val = tcg_temp_new(TCG_TYPE_TL);
    gen_qemu_ld32u(val, EA, ctx->mem_idx);
    tcg_temp_free(val);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
    tcg_temp_free(EA);
5512 5513 5514 5515
#endif
}

/* icbt */
5516
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527
{
    /* 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)
5528
    GEN_EXCP_PRIVOPC(ctx);
5529 5530
#else
    if (unlikely(!ctx->supervisor)) {
5531
        GEN_EXCP_PRIVOPC(ctx);
5532 5533 5534 5535 5536 5537 5538 5539 5540 5541
        return;
    }
    /* interpreted as no-op */
#endif
}

/* icread */
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
5542
    GEN_EXCP_PRIVOPC(ctx);
5543 5544
#else
    if (unlikely(!ctx->supervisor)) {
5545
        GEN_EXCP_PRIVOPC(ctx);
5546 5547 5548 5549 5550 5551 5552
        return;
    }
    /* interpreted as no-op */
#endif
}

/* rfci (supervisor only) */
5553
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
5554 5555
{
#if defined(CONFIG_USER_ONLY)
5556
    GEN_EXCP_PRIVOPC(ctx);
5557 5558
#else
    if (unlikely(!ctx->supervisor)) {
5559
        GEN_EXCP_PRIVOPC(ctx);
5560 5561 5562 5563
        return;
    }
    /* Restore CPU state */
    gen_op_40x_rfci();
5564
    GEN_SYNC(ctx);
5565 5566 5567 5568 5569 5570
#endif
}

GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
{
#if defined(CONFIG_USER_ONLY)
5571
    GEN_EXCP_PRIVOPC(ctx);
5572 5573
#else
    if (unlikely(!ctx->supervisor)) {
5574
        GEN_EXCP_PRIVOPC(ctx);
5575 5576 5577 5578
        return;
    }
    /* Restore CPU state */
    gen_op_rfci();
5579
    GEN_SYNC(ctx);
5580 5581 5582 5583
#endif
}

/* BookE specific */
5584
/* XXX: not implemented on 440 ? */
5585
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
5586 5587
{
#if defined(CONFIG_USER_ONLY)
5588
    GEN_EXCP_PRIVOPC(ctx);
5589 5590
#else
    if (unlikely(!ctx->supervisor)) {
5591
        GEN_EXCP_PRIVOPC(ctx);
5592 5593 5594
        return;
    }
    /* Restore CPU state */
5595
    gen_op_rfdi();
5596
    GEN_SYNC(ctx);
5597 5598 5599
#endif
}

5600
/* XXX: not implemented on 440 ? */
5601
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
5602 5603
{
#if defined(CONFIG_USER_ONLY)
5604
    GEN_EXCP_PRIVOPC(ctx);
5605 5606
#else
    if (unlikely(!ctx->supervisor)) {
5607
        GEN_EXCP_PRIVOPC(ctx);
5608 5609 5610 5611
        return;
    }
    /* Restore CPU state */
    gen_op_rfmci();
5612
    GEN_SYNC(ctx);
5613 5614
#endif
}
5615

5616
/* TLB management - PowerPC 405 implementation */
5617
/* tlbre */
5618
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
5619 5620
{
#if defined(CONFIG_USER_ONLY)
5621
    GEN_EXCP_PRIVOPC(ctx);
5622 5623
#else
    if (unlikely(!ctx->supervisor)) {
5624
        GEN_EXCP_PRIVOPC(ctx);
5625 5626 5627 5628
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
A
aurel32 已提交
5629
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5630
        gen_op_4xx_tlbre_hi();
A
aurel32 已提交
5631
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5632 5633
        break;
    case 1:
A
aurel32 已提交
5634
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5635
        gen_op_4xx_tlbre_lo();
A
aurel32 已提交
5636
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5637 5638
        break;
    default:
5639
        GEN_EXCP_INVAL(ctx);
5640
        break;
5641
    }
5642 5643 5644
#endif
}

5645
/* tlbsx - tlbsx. */
5646
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5647 5648
{
#if defined(CONFIG_USER_ONLY)
5649
    GEN_EXCP_PRIVOPC(ctx);
5650 5651
#else
    if (unlikely(!ctx->supervisor)) {
5652
        GEN_EXCP_PRIVOPC(ctx);
5653 5654
        return;
    }
5655
    gen_addr_reg_index(cpu_T[0], ctx);
5656
    gen_op_4xx_tlbsx();
5657
    if (Rc(ctx->opcode))
5658
        gen_op_4xx_tlbsx_check();
A
aurel32 已提交
5659
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5660
#endif
B
bellard 已提交
5661 5662
}

5663
/* tlbwe */
5664
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
B
bellard 已提交
5665
{
5666
#if defined(CONFIG_USER_ONLY)
5667
    GEN_EXCP_PRIVOPC(ctx);
5668 5669
#else
    if (unlikely(!ctx->supervisor)) {
5670
        GEN_EXCP_PRIVOPC(ctx);
5671 5672 5673 5674
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
A
aurel32 已提交
5675 5676
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5677 5678 5679
        gen_op_4xx_tlbwe_hi();
        break;
    case 1:
A
aurel32 已提交
5680 5681
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5682 5683 5684
        gen_op_4xx_tlbwe_lo();
        break;
    default:
5685
        GEN_EXCP_INVAL(ctx);
5686
        break;
5687
    }
5688 5689 5690
#endif
}

5691
/* TLB management - PowerPC 440 implementation */
5692
/* tlbre */
5693
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5694 5695
{
#if defined(CONFIG_USER_ONLY)
5696
    GEN_EXCP_PRIVOPC(ctx);
5697 5698
#else
    if (unlikely(!ctx->supervisor)) {
5699
        GEN_EXCP_PRIVOPC(ctx);
5700 5701 5702 5703 5704 5705
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
A
aurel32 已提交
5706
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5707
        gen_op_440_tlbre(rB(ctx->opcode));
A
aurel32 已提交
5708
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5709 5710
        break;
    default:
5711
        GEN_EXCP_INVAL(ctx);
5712 5713 5714 5715 5716 5717
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
5718
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5719 5720
{
#if defined(CONFIG_USER_ONLY)
5721
    GEN_EXCP_PRIVOPC(ctx);
5722 5723
#else
    if (unlikely(!ctx->supervisor)) {
5724
        GEN_EXCP_PRIVOPC(ctx);
5725 5726
        return;
    }
5727
    gen_addr_reg_index(cpu_T[0], ctx);
5728
    gen_op_440_tlbsx();
5729
    if (Rc(ctx->opcode))
5730
        gen_op_4xx_tlbsx_check();
A
aurel32 已提交
5731
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5732 5733 5734 5735
#endif
}

/* tlbwe */
5736
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5737 5738
{
#if defined(CONFIG_USER_ONLY)
5739
    GEN_EXCP_PRIVOPC(ctx);
5740 5741
#else
    if (unlikely(!ctx->supervisor)) {
5742
        GEN_EXCP_PRIVOPC(ctx);
5743 5744 5745 5746 5747 5748
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
A
aurel32 已提交
5749 5750
        tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
        tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5751
        gen_op_440_tlbwe(rB(ctx->opcode));
5752 5753
        break;
    default:
5754
        GEN_EXCP_INVAL(ctx);
5755 5756 5757 5758 5759
        break;
    }
#endif
}

5760
/* wrtee */
5761
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
5762 5763
{
#if defined(CONFIG_USER_ONLY)
5764
    GEN_EXCP_PRIVOPC(ctx);
5765 5766
#else
    if (unlikely(!ctx->supervisor)) {
5767
        GEN_EXCP_PRIVOPC(ctx);
5768 5769
        return;
    }
A
aurel32 已提交
5770
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rD(ctx->opcode)]);
5771
    gen_op_wrte();
J
j_mayer 已提交
5772 5773 5774
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
5775
    GEN_STOP(ctx);
5776 5777 5778 5779
#endif
}

/* wrteei */
5780
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
5781 5782
{
#if defined(CONFIG_USER_ONLY)
5783
    GEN_EXCP_PRIVOPC(ctx);
5784 5785
#else
    if (unlikely(!ctx->supervisor)) {
5786
        GEN_EXCP_PRIVOPC(ctx);
5787 5788
        return;
    }
5789
    tcg_gen_movi_tl(cpu_T[0], ctx->opcode & 0x00010000);
5790
    gen_op_wrte();
J
j_mayer 已提交
5791 5792 5793
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
5794
    GEN_STOP(ctx);
5795 5796 5797
#endif
}

J
j_mayer 已提交
5798
/* PowerPC 440 specific instructions */
5799 5800 5801
/* dlmzb */
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
{
A
aurel32 已提交
5802 5803
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
5804
    gen_op_440_dlmzb();
A
aurel32 已提交
5805
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
A
aurel32 已提交
5806 5807
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
    tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]);
5808 5809
    if (Rc(ctx->opcode)) {
        gen_op_440_dlmzb_update_Rc();
A
aurel32 已提交
5810
        tcg_gen_andi_i32(cpu_crf[0], cpu_T[0], 0xf);
5811 5812 5813 5814 5815 5816 5817 5818 5819 5820
    }
}

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

/* msync replaces sync on 440 */
5821
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
5822 5823 5824 5825 5826
{
    /* interpreted as no-op */
}

/* icbt */
5827
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
5828 5829 5830 5831 5832
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
5833 5834
}

5835 5836 5837
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

5838 5839 5840 5841 5842 5843 5844 5845 5846
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]);
}
5847 5848 5849

#define op_vr_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_VR_LD_TABLE(name)                                                  \
5850 5851
static GenOpFunc *gen_op_vr_l##name[NB_MEM_FUNCS] = {                         \
    GEN_MEM_FUNCS(vr_l##name),                                                \
5852 5853
};
#define OP_VR_ST_TABLE(name)                                                  \
5854 5855
static GenOpFunc *gen_op_vr_st##name[NB_MEM_FUNCS] = {                        \
    GEN_MEM_FUNCS(vr_st##name),                                               \
5856 5857 5858 5859 5860 5861 5862 5863 5864
};

#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;                                                               \
    }                                                                         \
5865
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
5866
    op_vr_ldst(vr_l##name);                                                   \
5867
    gen_store_avr(rD(ctx->opcode), 0);                                        \
5868 5869 5870 5871 5872 5873 5874 5875 5876
}

#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;                                                               \
    }                                                                         \
5877
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
5878
    gen_load_avr(0, rS(ctx->opcode));                                         \
5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893
    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);

5894 5895
/***                           SPE extension                               ***/
/* Register moves */
5896

A
aurel32 已提交
5897 5898 5899 5900
static always_inline void gen_load_gpr64(TCGv t, int reg) {
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
5901
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
5902
#endif
A
aurel32 已提交
5903
}
5904

A
aurel32 已提交
5905 5906 5907 5908 5909
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);
5910
    TCGv tmp = tcg_temp_new(TCG_TYPE_I64);
A
aurel32 已提交
5911 5912 5913
    tcg_gen_shri_i64(tmp, t, 32);
    tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
    tcg_temp_free(tmp);
5914
#endif
A
aurel32 已提交
5915
}
5916

5917 5918 5919 5920 5921 5922 5923 5924 5925 5926
#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 */
5927
static always_inline void gen_speundef (DisasContext *ctx)
5928
{
5929
    GEN_EXCP_INVAL(ctx);
5930 5931 5932
}

/* SPE load and stores */
5933
static always_inline void gen_addr_spe_imm_index (TCGv EA, DisasContext *ctx, int sh)
5934 5935 5936
{
    target_long simm = rB(ctx->opcode);

5937 5938 5939 5940 5941 5942
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(EA, simm << sh);
    else if (likely(simm != 0))
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm << sh);
    else
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
5943 5944 5945 5946
}

#define op_spe_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_SPE_LD_TABLE(name)                                                 \
5947 5948
static GenOpFunc *gen_op_spe_l##name[NB_MEM_FUNCS] = {                        \
    GEN_MEM_FUNCS(spe_l##name),                                               \
5949 5950
};
#define OP_SPE_ST_TABLE(name)                                                 \
5951 5952
static GenOpFunc *gen_op_spe_st##name[NB_MEM_FUNCS] = {                       \
    GEN_MEM_FUNCS(spe_st##name),                                              \
5953
};
5954 5955

#define GEN_SPE_LD(name, sh)                                                  \
5956
static always_inline void gen_evl##name (DisasContext *ctx)                   \
5957 5958
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5959
        GEN_EXCP_NO_AP(ctx);                                                  \
5960 5961
        return;                                                               \
    }                                                                         \
5962
    gen_addr_spe_imm_index(cpu_T[0], ctx, sh);                                \
5963
    op_spe_ldst(spe_l##name);                                                 \
A
aurel32 已提交
5964
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]);                             \
5965 5966 5967
}

#define GEN_SPE_LDX(name)                                                     \
5968
static always_inline void gen_evl##name##x (DisasContext *ctx)                \
5969 5970
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5971
        GEN_EXCP_NO_AP(ctx);                                                  \
5972 5973
        return;                                                               \
    }                                                                         \
5974
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
5975
    op_spe_ldst(spe_l##name);                                                 \
A
aurel32 已提交
5976
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]);                             \
5977 5978 5979 5980 5981 5982 5983 5984
}

#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)                                                  \
5985
static always_inline void gen_evst##name (DisasContext *ctx)                  \
5986 5987
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5988
        GEN_EXCP_NO_AP(ctx);                                                  \
5989 5990
        return;                                                               \
    }                                                                         \
5991
    gen_addr_spe_imm_index(cpu_T[0], ctx, sh);                                \
A
aurel32 已提交
5992
    gen_load_gpr64(cpu_T64[1], rS(ctx->opcode));                              \
5993 5994 5995 5996
    op_spe_ldst(spe_st##name);                                                \
}

#define GEN_SPE_STX(name)                                                     \
5997
static always_inline void gen_evst##name##x (DisasContext *ctx)               \
5998 5999
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6000
        GEN_EXCP_NO_AP(ctx);                                                  \
6001 6002
        return;                                                               \
    }                                                                         \
6003
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
A
aurel32 已提交
6004
    gen_load_gpr64(cpu_T64[1], rS(ctx->opcode));                              \
6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018
    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)                                                \
6019
static always_inline void gen_##name (DisasContext *ctx)                      \
6020 6021
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6022
        GEN_EXCP_NO_AP(ctx);                                                  \
6023 6024
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6025 6026
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
6027
    gen_op_##name();                                                          \
A
aurel32 已提交
6028
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6029 6030
}

6031
#define GEN_SPEOP_TCG_ARITH2(name, tcg_op)                                    \
6032 6033 6034 6035 6036 6037 6038 6039 6040 6041
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    TCGv t0 = tcg_temp_new(TCG_TYPE_I64);                                     \
    TCGv t1 = tcg_temp_new(TCG_TYPE_I64);                                     \
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
6042
    tcg_op(t0, t0, t1);                                                       \
6043 6044 6045 6046 6047
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
    tcg_temp_free(t0);                                                        \
    tcg_temp_free(t1);                                                        \
}

6048
#define GEN_SPEOP_ARITH1(name)                                                \
6049
static always_inline void gen_##name (DisasContext *ctx)                      \
6050 6051
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6052
        GEN_EXCP_NO_AP(ctx);                                                  \
6053 6054
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6055
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
6056
    gen_op_##name();                                                          \
A
aurel32 已提交
6057
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6058 6059 6060
}

#define GEN_SPEOP_COMP(name)                                                  \
6061
static always_inline void gen_##name (DisasContext *ctx)                      \
6062 6063
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6064
        GEN_EXCP_NO_AP(ctx);                                                  \
6065 6066
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6067 6068
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
6069
    gen_op_##name();                                                          \
A
aurel32 已提交
6070
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);              \
6071 6072 6073
}

/* Logical */
6074 6075 6076 6077 6078 6079 6080 6081
GEN_SPEOP_TCG_ARITH2(evand, tcg_gen_and_i64);
GEN_SPEOP_TCG_ARITH2(evandc, tcg_gen_andc_i64);
GEN_SPEOP_TCG_ARITH2(evxor, tcg_gen_xor_i64);
GEN_SPEOP_TCG_ARITH2(evor, tcg_gen_or_i64);
GEN_SPEOP_TCG_ARITH2(evnor, tcg_gen_nor_i64);
GEN_SPEOP_TCG_ARITH2(eveqv, tcg_gen_eqv_i64);
GEN_SPEOP_TCG_ARITH2(evorc, tcg_gen_orc_i64);
GEN_SPEOP_TCG_ARITH2(evnand, tcg_gen_nand_i64);
6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100
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);
6101
static always_inline void gen_brinc (DisasContext *ctx)
6102 6103
{
    /* Note: brinc is usable even if SPE is disabled */
A
aurel32 已提交
6104 6105
    tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
6106
    gen_op_brinc();
A
aurel32 已提交
6107
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
6108 6109 6110
}

#define GEN_SPEOP_ARITH_IMM2(name)                                            \
6111
static always_inline void gen_##name##i (DisasContext *ctx)                   \
6112 6113
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6114
        GEN_EXCP_NO_AP(ctx);                                                  \
6115 6116
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6117
    gen_load_gpr64(cpu_T64[0], rB(ctx->opcode));                              \
6118 6119
    gen_op_splatwi_T1_64(rA(ctx->opcode));                                    \
    gen_op_##name();                                                          \
A
aurel32 已提交
6120
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6121 6122 6123
}

#define GEN_SPEOP_LOGIC_IMM2(name)                                            \
6124
static always_inline void gen_##name##i (DisasContext *ctx)                   \
6125 6126
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6127
        GEN_EXCP_NO_AP(ctx);                                                  \
6128 6129
        return;                                                               \
    }                                                                         \
A
aurel32 已提交
6130
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
6131 6132
    gen_op_splatwi_T1_64(rB(ctx->opcode));                                    \
    gen_op_##name();                                                          \
A
aurel32 已提交
6133
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146
}

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

6147
static always_inline void gen_evsplati (DisasContext *ctx)
6148 6149 6150 6151
{
    int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;

    gen_op_splatwi_T0_64(imm);
A
aurel32 已提交
6152
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
6153 6154
}

6155
static always_inline void gen_evsplatfi (DisasContext *ctx)
6156 6157 6158 6159
{
    uint32_t imm = rA(ctx->opcode) << 27;

    gen_op_splatwi_T0_64(imm);
A
aurel32 已提交
6160
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195
}

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

6196
static always_inline void gen_evsel (DisasContext *ctx)
6197 6198
{
    if (unlikely(!ctx->spe_enabled)) {
6199
        GEN_EXCP_NO_AP(ctx);
6200 6201
        return;
    }
A
aurel32 已提交
6202
    tcg_gen_mov_i32(cpu_T[0], cpu_crf[ctx->opcode & 0x7]);
A
aurel32 已提交
6203 6204
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));
6205
    gen_op_evsel();
A
aurel32 已提交
6206
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
6207 6208
}

6209
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
6210 6211 6212
{
    gen_evsel(ctx);
}
6213
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
6214 6215 6216
{
    gen_evsel(ctx);
}
6217
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
6218 6219 6220
{
    gen_evsel(ctx);
}
6221
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235
{
    gen_evsel(ctx);
}

/* Load and stores */
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);

#define _GEN_OP_SPE_STWWE(suffix)                                             \
6236
static always_inline void gen_op_spe_stwwe_##suffix (void)                    \
6237 6238 6239 6240 6241
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_##suffix();                                              \
}
#define _GEN_OP_SPE_STWWE_LE(suffix)                                          \
6242
static always_inline void gen_op_spe_stwwe_le_##suffix (void)                 \
6243 6244 6245 6246 6247 6248 6249 6250
{                                                                             \
    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);                                                 \
6251
static always_inline void gen_op_spe_stwwe_64_##suffix (void)                 \
6252 6253 6254 6255
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_64_##suffix();                                           \
}                                                                             \
6256
static always_inline void gen_op_spe_stwwe_le_64_##suffix (void)              \
6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269
{                                                                             \
    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);
6270 6271
GEN_OP_SPE_STWWE(kernel);
GEN_OP_SPE_STWWE(hypv);
6272 6273 6274 6275 6276
#endif /* defined(CONFIG_USER_ONLY) */
GEN_SPEOP_ST(wwe, 2);
GEN_SPEOP_ST(wwo, 2);

#define GEN_SPE_LDSPLAT(name, op, suffix)                                     \
6277
static always_inline void gen_op_spe_l##name##_##suffix (void)                \
6278 6279 6280 6281 6282 6283
{                                                                             \
    gen_op_##op##_##suffix();                                                 \
    gen_op_splatw_T1_64();                                                    \
}

#define GEN_OP_SPE_LHE(suffix)                                                \
6284
static always_inline void gen_op_spe_lhe_##suffix (void)                      \
6285 6286 6287 6288 6289 6290
{                                                                             \
    gen_op_spe_lh_##suffix();                                                 \
    gen_op_sli16_T1_64();                                                     \
}

#define GEN_OP_SPE_LHX(suffix)                                                \
6291
static always_inline void gen_op_spe_lhx_##suffix (void)                      \
6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321
{                                                                             \
    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);
6322 6323
GEN_OP_SPE_LHE(kernel);
GEN_OP_SPE_LHE(hypv);
6324
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
6325 6326
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, hypv);
6327
GEN_OP_SPE_LHE(le_user);
6328 6329
GEN_OP_SPE_LHE(le_kernel);
GEN_OP_SPE_LHE(le_hypv);
6330
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
6331 6332
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_hypv);
6333
GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
6334 6335
GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, hypv);
6336
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
6337 6338
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_hypv);
6339
GEN_OP_SPE_LHX(user);
6340 6341
GEN_OP_SPE_LHX(kernel);
GEN_OP_SPE_LHX(hypv);
6342
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
6343 6344
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, hypv);
6345
GEN_OP_SPE_LHX(le_user);
6346 6347
GEN_OP_SPE_LHX(le_kernel);
GEN_OP_SPE_LHX(le_hypv);
6348
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
6349 6350
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_hypv);
6351 6352
#if defined(TARGET_PPC64)
GEN_OP_SPE_LHE(64_user);
6353 6354
GEN_OP_SPE_LHE(64_kernel);
GEN_OP_SPE_LHE(64_hypv);
6355
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
6356 6357
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_hypv);
6358
GEN_OP_SPE_LHE(le_64_user);
6359 6360
GEN_OP_SPE_LHE(le_64_kernel);
GEN_OP_SPE_LHE(le_64_hypv);
6361
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
6362 6363
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_hypv);
6364
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
6365 6366
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_hypv);
6367
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
6368 6369
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_hypv);
6370
GEN_OP_SPE_LHX(64_user);
6371 6372
GEN_OP_SPE_LHX(64_kernel);
GEN_OP_SPE_LHX(64_hypv);
6373
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
6374 6375
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_hypv);
6376
GEN_OP_SPE_LHX(le_64_user);
6377 6378
GEN_OP_SPE_LHX(le_64_kernel);
GEN_OP_SPE_LHX(le_64_hypv);
6379
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
6380 6381
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_hypv);
6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 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 6486
#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)                                               \
6487
static always_inline void gen_##name (DisasContext *ctx)                      \
6488
{                                                                             \
A
aurel32 已提交
6489
    gen_load_gpr64(cpu_T64[0], rB(ctx->opcode));                              \
6490
    gen_op_##name();                                                          \
A
aurel32 已提交
6491
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567
}

/* 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 */
6568
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
6569 6570 6571 6572 6573 6574 6575 6576 6577
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); //
6578 6579
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634
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 已提交
6635 6636 6637
/* End opcode list */
GEN_OPCODE_MARK(end);

6638
#include "translate_init.c"
6639
#include "helper_regs.h"
B
bellard 已提交
6640

6641
/*****************************************************************************/
6642
/* Misc PowerPC helpers */
6643 6644 6645
void cpu_dump_state (CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
B
bellard 已提交
6646
{
6647 6648 6649
#define RGPL  4
#define RFPL  4

B
bellard 已提交
6650 6651
    int i;

J
j_mayer 已提交
6652
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
A
aurel32 已提交
6653
                env->nip, env->lr, env->ctr, env->xer);
6654 6655
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
6656
#if !defined(NO_TIMER_DUMP)
J
j_mayer 已提交
6657
    cpu_fprintf(f, "TB %08x %08x "
6658 6659 6660 6661
#if !defined(CONFIG_USER_ONLY)
                "DECR %08x"
#endif
                "\n",
J
j_mayer 已提交
6662
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
6663 6664 6665 6666
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
6667
#endif
6668
    for (i = 0; i < 32; i++) {
6669 6670
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
6671
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
6672
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
6673
            cpu_fprintf(f, "\n");
6674
    }
6675
    cpu_fprintf(f, "CR ");
6676
    for (i = 0; i < 8; i++)
B
bellard 已提交
6677 6678
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
6679 6680 6681 6682 6683 6684 6685 6686
    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 已提交
6687
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
6688
    }
6689
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
6690 6691 6692
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
6693
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
6694
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
6695
            cpu_fprintf(f, "\n");
B
bellard 已提交
6696
    }
6697
#if !defined(CONFIG_USER_ONLY)
6698
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
6699
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
6700
#endif
B
bellard 已提交
6701

6702 6703
#undef RGPL
#undef RFPL
B
bellard 已提交
6704 6705
}

6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752
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
}

6753
/*****************************************************************************/
6754 6755 6756
static always_inline void gen_intermediate_code_internal (CPUState *env,
                                                          TranslationBlock *tb,
                                                          int search_pc)
B
bellard 已提交
6757
{
6758
    DisasContext ctx, *ctxp = &ctx;
B
bellard 已提交
6759
    opc_handler_t **table, *handler;
B
bellard 已提交
6760
    target_ulong pc_start;
B
bellard 已提交
6761
    uint16_t *gen_opc_end;
6762
    int supervisor, little_endian;
B
bellard 已提交
6763
    int j, lj = -1;
P
pbrook 已提交
6764 6765
    int num_insns;
    int max_insns;
B
bellard 已提交
6766 6767 6768

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6769 6770 6771
#if defined(OPTIMIZE_FPRF_UPDATE)
    gen_fprf_ptr = gen_fprf_buf;
#endif
B
bellard 已提交
6772
    ctx.nip = pc_start;
B
bellard 已提交
6773
    ctx.tb = tb;
6774
    ctx.exception = POWERPC_EXCP_NONE;
6775
    ctx.spr_cb = env->spr_cb;
6776 6777
    supervisor = env->mmu_idx;
#if !defined(CONFIG_USER_ONLY)
6778
    ctx.supervisor = supervisor;
6779
#endif
6780
    little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
6781 6782
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
6783
    ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
6784
#else
6785
    ctx.mem_idx = (supervisor << 1) | little_endian;
6786
#endif
6787
    ctx.dcache_line_size = env->dcache_line_size;
B
bellard 已提交
6788
    ctx.fpu_enabled = msr_fp;
6789
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
6790 6791 6792
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
6793 6794 6795 6796
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
6797
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
6798
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
6799
    else
6800
        ctx.singlestep_enabled = 0;
6801
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
6802 6803 6804
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
6805
#if defined (DO_SINGLE_STEP) && 0
6806 6807 6808
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
6809 6810 6811 6812 6813 6814
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
6815
    /* Set env in case of segfault during code fetch */
6816
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
6817 6818
        if (unlikely(env->nb_breakpoints > 0)) {
            for (j = 0; j < env->nb_breakpoints; j++) {
6819
                if (env->breakpoints[j] == ctx.nip) {
6820
                    gen_update_nip(&ctx, ctx.nip);
6821 6822 6823 6824 6825
                    gen_op_debug();
                    break;
                }
            }
        }
6826
        if (unlikely(search_pc)) {
B
bellard 已提交
6827 6828 6829 6830 6831
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
6832
                gen_opc_pc[lj] = ctx.nip;
B
bellard 已提交
6833
                gen_opc_instr_start[lj] = 1;
P
pbrook 已提交
6834
                gen_opc_icount[lj] = num_insns;
B
bellard 已提交
6835 6836
            }
        }
6837 6838
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
B
bellard 已提交
6839
            fprintf(logfile, "----------------\n");
6840
            fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
6841
                    ctx.nip, supervisor, (int)msr_ir);
6842 6843
        }
#endif
P
pbrook 已提交
6844 6845
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
6846 6847 6848 6849
        if (unlikely(little_endian)) {
            ctx.opcode = bswap32(ldl_code(ctx.nip));
        } else {
            ctx.opcode = ldl_code(ctx.nip);
6850
        }
6851 6852
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
6853
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6854
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
6855
                    opc3(ctx.opcode), little_endian ? "little" : "big");
B
bellard 已提交
6856 6857
        }
#endif
B
bellard 已提交
6858
        ctx.nip += 4;
6859
        table = env->opcodes;
P
pbrook 已提交
6860
        num_insns++;
B
bellard 已提交
6861 6862 6863 6864 6865 6866 6867 6868 6869 6870
        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 ? */
6871
        if (unlikely(handler->handler == &gen_invalid)) {
J
j_mayer 已提交
6872
            if (loglevel != 0) {
6873
                fprintf(logfile, "invalid/unsupported opcode: "
6874
                        "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
6875
                        opc1(ctx.opcode), opc2(ctx.opcode),
6876
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
6877 6878
            } else {
                printf("invalid/unsupported opcode: "
6879
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
B
bellard 已提交
6880
                       opc1(ctx.opcode), opc2(ctx.opcode),
6881
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
6882
            }
6883 6884
        } else {
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
J
j_mayer 已提交
6885
                if (loglevel != 0) {
B
bellard 已提交
6886
                    fprintf(logfile, "invalid bits: %08x for opcode: "
6887
                            "%02x - %02x - %02x (%08x) " ADDRX "\n",
B
bellard 已提交
6888 6889
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
                            opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
6890
                            ctx.opcode, ctx.nip - 4);
6891 6892
                } else {
                    printf("invalid bits: %08x for opcode: "
6893
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
6894 6895
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
                           opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
6896
                           ctx.opcode, ctx.nip - 4);
6897
                }
6898
                GEN_EXCP_INVAL(ctxp);
B
bellard 已提交
6899
                break;
B
bellard 已提交
6900 6901
            }
        }
B
bellard 已提交
6902
        (*(handler->handler))(&ctx);
6903 6904 6905
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
6906
        /* Check trace mode exceptions */
6907 6908 6909 6910 6911
        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)) {
6912
            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
6913
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
6914 6915
                            (env->singlestep_enabled) ||
                            num_insns >= max_insns)) {
6916 6917 6918
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
6919
            break;
6920
        }
6921 6922 6923 6924
#if defined (DO_SINGLE_STEP)
        break;
#endif
    }
P
pbrook 已提交
6925 6926
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
6927
    if (ctx.exception == POWERPC_EXCP_NONE) {
6928
        gen_goto_tb(&ctx, 0, ctx.nip);
6929
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
6930 6931 6932 6933
        if (unlikely(env->singlestep_enabled)) {
            gen_update_nip(&ctx, ctx.nip);
            gen_op_debug();
        }
6934
        /* Generate the return instruction */
B
bellard 已提交
6935
        tcg_gen_exit_tb(0);
6936
    }
P
pbrook 已提交
6937
    gen_icount_end(tb, num_insns);
B
bellard 已提交
6938
    *gen_opc_ptr = INDEX_op_end;
6939
    if (unlikely(search_pc)) {
6940 6941 6942 6943 6944
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
B
bellard 已提交
6945
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
6946
        tb->icount = num_insns;
6947
    }
6948
#if defined(DEBUG_DISAS)
6949
    if (loglevel & CPU_LOG_TB_CPU) {
6950
        fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
B
bellard 已提交
6951
        cpu_dump_state(env, logfile, fprintf, 0);
6952 6953
    }
    if (loglevel & CPU_LOG_TB_IN_ASM) {
6954
        int flags;
6955
        flags = env->bfd_mach;
6956
        flags |= little_endian << 16;
B
bellard 已提交
6957
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6958
        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
B
bellard 已提交
6959
        fprintf(logfile, "\n");
6960
    }
B
bellard 已提交
6961 6962 6963
#endif
}

6964
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
6965
{
6966
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
6967 6968
}

6969
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
6970
{
6971
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
6972
}
A
aurel32 已提交
6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014

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;
}