translate.c 267.9 KB
Newer Older
B
bellard 已提交
1
/*
2
 *  PowerPC emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
B
bellard 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
B
bellard 已提交
20 21 22 23 24 25
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

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

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

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

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

46 47
/*****************************************************************************/
/* Code translation helpers                                                  */
B
bellard 已提交
48

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

/* dyngen register indexes */
static TCGv cpu_T[3];
#if defined(TARGET_PPC64)
#define cpu_T64 cpu_T
#else
P
pbrook 已提交
76
static TCGv_i64 cpu_T64[3];
A
aurel32 已提交
77
#endif
A
aurel32 已提交
78
static TCGv_i64 cpu_FT[2];
P
pbrook 已提交
79
static TCGv_i64 cpu_AVRh[3], cpu_AVRl[3];
P
pbrook 已提交
80 81 82 83 84

#include "gen-icount.h"

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

P
pbrook 已提交
89 90
    if (done_init)
        return;
A
aurel32 已提交
91

P
pbrook 已提交
92
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
A
aurel32 已提交
93
#if TARGET_LONG_BITS > HOST_LONG_BITS
P
pbrook 已提交
94 95 96
    cpu_T[0] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t0), "T0");
    cpu_T[1] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t1), "T1");
    cpu_T[2] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t2), "T2");
A
aurel32 已提交
97
#else
P
pbrook 已提交
98 99
    cpu_T[0] = tcg_global_reg_new(TCG_AREG1, "T0");
    cpu_T[1] = tcg_global_reg_new(TCG_AREG2, "T1");
100 101 102 103 104
#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.
     */
P
pbrook 已提交
105
    cpu_T[2] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t2), "T2");
106
#else
P
pbrook 已提交
107
    cpu_T[2] = tcg_global_reg_new(TCG_AREG3, "T2");
A
aurel32 已提交
108
#endif
109
#endif
A
aurel32 已提交
110
#if !defined(TARGET_PPC64)
P
pbrook 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124
    cpu_T64[0] = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, t0_64),
                                        "T0_64");
    cpu_T64[1] = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, t1_64),
                                        "T1_64");
    cpu_T64[2] = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, t2_64),
                                        "T2_64");
#endif

    cpu_FT[0] = tcg_global_mem_new_i64(TCG_AREG0,
                                       offsetof(CPUState, ft0), "FT0");
    cpu_FT[1] = tcg_global_mem_new_i64(TCG_AREG0,
                                       offsetof(CPUState, ft1), "FT1");

    cpu_AVRh[0] = tcg_global_mem_new_i64(TCG_AREG0,
125
                                     offsetof(CPUState, avr0.u64[0]), "AVR0H");
P
pbrook 已提交
126
    cpu_AVRl[0] = tcg_global_mem_new_i64(TCG_AREG0,
127
                                     offsetof(CPUState, avr0.u64[1]), "AVR0L");
P
pbrook 已提交
128
    cpu_AVRh[1] = tcg_global_mem_new_i64(TCG_AREG0,
129
                                     offsetof(CPUState, avr1.u64[0]), "AVR1H");
P
pbrook 已提交
130
    cpu_AVRl[1] = tcg_global_mem_new_i64(TCG_AREG0,
131
                                     offsetof(CPUState, avr1.u64[1]), "AVR1L");
P
pbrook 已提交
132
    cpu_AVRh[2] = tcg_global_mem_new_i64(TCG_AREG0,
133
                                     offsetof(CPUState, avr2.u64[0]), "AVR2H");
P
pbrook 已提交
134
    cpu_AVRl[2] = tcg_global_mem_new_i64(TCG_AREG0,
135 136
                                     offsetof(CPUState, avr2.u64[1]), "AVR2L");

A
aurel32 已提交
137
    p = cpu_reg_names;
A
aurel32 已提交
138 139 140

    for (i = 0; i < 8; i++) {
        sprintf(p, "crf%d", i);
P
pbrook 已提交
141 142
        cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
                                            offsetof(CPUState, crf[i]), p);
A
aurel32 已提交
143 144 145
        p += 5;
    }

A
aurel32 已提交
146 147
    for (i = 0; i < 32; i++) {
        sprintf(p, "r%d", i);
P
pbrook 已提交
148
        cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
149 150 151 152
                                        offsetof(CPUState, gpr[i]), p);
        p += (i < 10) ? 3 : 4;
#if !defined(TARGET_PPC64)
        sprintf(p, "r%dH", i);
P
pbrook 已提交
153 154
        cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
                                             offsetof(CPUState, gprh[i]), p);
A
aurel32 已提交
155 156
        p += (i < 10) ? 4 : 5;
#endif
157

A
aurel32 已提交
158
        sprintf(p, "fp%d", i);
P
pbrook 已提交
159 160
        cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                            offsetof(CPUState, fpr[i]), p);
A
aurel32 已提交
161
        p += (i < 10) ? 4 : 5;
A
aurel32 已提交
162

163
        sprintf(p, "avr%dH", i);
P
pbrook 已提交
164
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
165 166
                                         offsetof(CPUState, avr[i].u64[0]), p);
        p += (i < 10) ? 6 : 7;
A
aurel32 已提交
167

168
        sprintf(p, "avr%dL", i);
P
pbrook 已提交
169
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
170 171
                                         offsetof(CPUState, avr[i].u64[1]), p);
        p += (i < 10) ? 6 : 7;
A
aurel32 已提交
172
    }
A
aurel32 已提交
173

P
pbrook 已提交
174
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
175 176
                                 offsetof(CPUState, nip), "nip");

P
pbrook 已提交
177
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
178 179
                                 offsetof(CPUState, ctr), "ctr");

P
pbrook 已提交
180
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
181 182
                                offsetof(CPUState, lr), "lr");

P
pbrook 已提交
183
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
A
aurel32 已提交
184 185
                                 offsetof(CPUState, xer), "xer");

P
pbrook 已提交
186 187
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
                                       offsetof(CPUState, fpscr), "fpscr");
188

A
aurel32 已提交
189
    /* register helpers */
P
pbrook 已提交
190
#define GEN_HELPER 2
A
aurel32 已提交
191 192
#include "helper.h"

P
pbrook 已提交
193 194 195
    done_init = 1;
}

196 197 198 199
#if defined(OPTIMIZE_FPRF_UPDATE)
static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
static uint16_t **gen_fprf_ptr;
#endif
B
bellard 已提交
200 201 202 203

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

224
struct opc_handler_t {
B
bellard 已提交
225 226
    /* invalid bits */
    uint32_t inval;
227
    /* instruction type */
228
    uint64_t type;
B
bellard 已提交
229 230
    /* handler */
    void (*handler)(DisasContext *ctx);
231
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
232
    const char *oname;
233 234
#endif
#if defined(DO_PPC_STATISTICS)
235 236
    uint64_t count;
#endif
237
};
B
bellard 已提交
238

239 240 241 242 243 244 245
static always_inline void gen_reset_fpstatus (void)
{
#ifdef CONFIG_SOFTFLOAT
    gen_op_reset_fpstatus();
#endif
}

A
aurel32 已提交
246
static always_inline void gen_compute_fprf (TCGv arg, int set_fprf, int set_rc)
247
{
A
aurel32 已提交
248 249
    TCGv t0 = tcg_temp_new_i32();

250 251 252 253 254
    if (set_fprf != 0) {
        /* This case might be optimized later */
#if defined(OPTIMIZE_FPRF_UPDATE)
        *gen_fprf_ptr++ = gen_opc_ptr;
#endif
A
aurel32 已提交
255 256
        tcg_gen_movi_tl(t0, 1);
        gen_helper_compute_fprf(t0, arg, t0);
P
pbrook 已提交
257
        if (unlikely(set_rc)) {
A
aurel32 已提交
258
            tcg_gen_movi_i32(cpu_crf[1], t0);
P
pbrook 已提交
259
        }
A
aurel32 已提交
260
        gen_helper_float_check_status();
261 262
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
A
aurel32 已提交
263 264 265
        tcg_gen_movi_tl(t0, 0);
        gen_helper_compute_fprf(t0, arg, t0);
        tcg_gen_movi_i32(cpu_crf[1], t0);
266
        if (set_fprf)
A
aurel32 已提交
267
            gen_helper_float_check_status();
268
    }
A
aurel32 已提交
269 270

    tcg_temp_free(t0);
271 272 273 274 275 276 277 278 279 280 281 282 283
}

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
    TCGv t0, t1;
P
pbrook 已提交
754 755
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
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;
P
pbrook 已提交
844
    TCGv_i32 t0;
845 846 847 848 849

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

    mask = 1 << (3 - (bi & 0x03));
P
pbrook 已提交
850
    t0 = tcg_temp_new_i32();
851 852
    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
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    else
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    gen_set_label(l2);
P
pbrook 已提交
861
    tcg_temp_free_i32(t0);
862 863
}

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

866 867 868 869
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 已提交
870

871 872 873
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
P
pbrook 已提交
874
    t0 = tcg_temp_local_new();
875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
    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 已提交
896 897
}

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

#if defined(TARGET_PPC64)
903 904
    if (!(ctx->sf_mode)) {
        TCGv t0, t1;
P
pbrook 已提交
905 906
        t0 = tcg_temp_new();
        t1 = tcg_temp_new();
907

908 909 910 911
        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 已提交
912
        } else {
913 914
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
        }
915 916 917 918
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
        gen_set_label(l1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
919 920
    } else
#endif
921 922 923 924 925 926 927 928
    {
        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);
929
    }
930 931
}

932 933 934 935 936
/* 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;
937

938
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
939
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
940 941
        t0 = ret;
    } else {
P
pbrook 已提交
942
        t0 = tcg_temp_local_new();
943
    }
B
bellard 已提交
944

945
    if (add_ca) {
P
pbrook 已提交
946
        t1 = tcg_temp_local_new();
947 948 949
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
    }
B
bellard 已提交
950

951 952 953 954 955 956 957 958 959 960
    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 已提交
961

962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978
    tcg_gen_add_tl(t0, arg1, arg2);

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

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

P
pbrook 已提交
979
    if (!TCGV_EQUAL(t0, ret)) {
980 981 982
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
A
aurel32 已提交
983
}
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
/* 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)
1021
{
1022 1023 1024 1025 1026 1027 1028 1029
    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);
    }
1030
}
1031 1032 1033
/* addic  addic.*/
static always_inline void gen_op_addic (DisasContext *ctx, TCGv ret, TCGv arg1,
                                        int compute_Rc0)
1034
{
1035 1036 1037 1038 1039 1040
    target_long simm = SIMM(ctx->opcode);

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

    if (likely(simm != 0)) {
P
pbrook 已提交
1041
        TCGv t0 = tcg_temp_local_new();
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
        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);
    }
1052
}
1053
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1054
{
1055
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1056
}
1057
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1058
{
1059
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1060
}
1061 1062
/* addis */
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1063
{
1064 1065 1066 1067 1068 1069 1070 1071
    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);
    }
1072
}
1073 1074 1075

static always_inline void gen_op_arith_divw (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
                                             int sign, int compute_ov)
1076
{
1077 1078
    int l1 = gen_new_label();
    int l2 = gen_new_label();
P
pbrook 已提交
1079 1080
    TCGv_i32 t0 = tcg_temp_local_new_i32();
    TCGv_i32 t1 = tcg_temp_local_new_i32();
1081

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

    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
    if (sign) {
1137
        int l3 = gen_new_label();
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
        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);
1161
}
1162 1163 1164
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)                      \
{                                                                             \
1165 1166 1167
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
                      sign, compute_ov);                                      \
1168 1169 1170 1171 1172 1173 1174
}
/* 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);
1175
#endif
1176 1177 1178

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

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

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

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

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

/* 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 已提交
1342
{
1343
    TCGv t0, t1;
1344

1345
    if ((!compute_ca && !compute_ov) ||
P
pbrook 已提交
1346
        (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1347
        t0 = ret;
J
j_mayer 已提交
1348
    } else {
P
pbrook 已提交
1349
        t0 = tcg_temp_local_new();
1350
    }
1351

1352
    if (add_ca) {
P
pbrook 已提交
1353
        t1 = tcg_temp_local_new();
1354 1355
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
1356
    }
B
bellard 已提交
1357

1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
    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 已提交
1376
    } else {
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
        tcg_gen_sub_tl(t0, arg2, arg1);
        if (compute_ca) {
            gen_op_arith_compute_ca(ctx, t0, arg2, 1);
        }
    }
    if (compute_ov) {
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
    }

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

P
pbrook 已提交
1389
    if (!TCGV_EQUAL(t0, ret)) {
1390 1391
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
B
bellard 已提交
1392 1393
    }
}
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
/* 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 已提交
1428 1429 1430
/* subfic */
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1431 1432
    /* Start with XER CA and OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
P
pbrook 已提交
1433
    TCGv t0 = tcg_temp_local_new();
1434 1435 1436 1437 1438 1439
    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 已提交
1440 1441 1442
}

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

1452
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
1453
GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)                          \
B
bellard 已提交
1454
{                                                                             \
1455
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1456
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1457
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
B
bellard 已提交
1458 1459 1460
}

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

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

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

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

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
1614
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
B
bellard 已提交
1615 1616 1617 1618
}
/* xoris */
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1619
    target_ulong uimm = UIMM(ctx->opcode);
1620 1621 1622 1623 1624

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

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

B
bellard 已提交
1650 1651 1652 1653
/***                             Integer rotate                            ***/
/* rlwimi & rlwimi. */
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1654
    uint32_t mb, me, sh;
B
bellard 已提交
1655 1656 1657

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

B
bellard 已提交
1694 1695 1696
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1697 1698 1699 1700 1701

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

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

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

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

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

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

J
j_mayer 已提交
1851 1852
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1853 1854 1855 1856
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

1857 1858
static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
                                     uint32_t me)
J
j_mayer 已提交
1859
{
1860
    TCGv t0;
1861 1862 1863

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
P
pbrook 已提交
1864
    t0 = tcg_temp_new();
1865
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1866
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
J
j_mayer 已提交
1867
    if (unlikely(mb != 0 || me != 63)) {
1868 1869 1870 1871 1872
        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 已提交
1873
    if (unlikely(Rc(ctx->opcode) != 0))
1874
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1875
}
J
j_mayer 已提交
1876

1877
/* rldcl - rldcl. */
1878
static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1879
{
J
j_mayer 已提交
1880
    uint32_t mb;
1881

J
j_mayer 已提交
1882
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1883
    gen_rldnm(ctx, mb, 63);
1884
}
1885
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1886
/* rldcr - rldcr. */
1887
static always_inline void gen_rldcr (DisasContext *ctx, int men)
1888
{
J
j_mayer 已提交
1889
    uint32_t me;
1890

J
j_mayer 已提交
1891
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1892
    gen_rldnm(ctx, 0, me);
1893
}
1894
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1895
/* rldimi - rldimi. */
1896
static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1897
{
1898
    uint32_t sh, mb, me;
1899

J
j_mayer 已提交
1900 1901
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
1902
    me = 63 - sh;
1903 1904 1905 1906 1907 1908
    if (unlikely(sh == 0 && mb == 0)) {
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
    } else {
        TCGv t0, t1;
        target_ulong mask;

P
pbrook 已提交
1909
        t0 = tcg_temp_new();
1910
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
P
pbrook 已提交
1911
        t1 = tcg_temp_new();
1912 1913 1914 1915 1916 1917
        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 已提交
1918 1919
    }
    if (unlikely(Rc(ctx->opcode) != 0))
1920
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1921
}
1922
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1923 1924
#endif

B
bellard 已提交
1925 1926
/***                             Integer shift                             ***/
/* slw & slw. */
1927 1928
GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER)
{
1929
    TCGv t0;
1930 1931 1932 1933
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();

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

P
pbrook 已提交
1992
    t0 = tcg_temp_local_new();
A
aurel32 已提交
1993 1994
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
1995 1996 1997
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
    tcg_gen_br(l2);
    gen_set_label(l1);
P
pbrook 已提交
1998
    t1 = tcg_temp_new();
1999 2000 2001
    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);
2002
    gen_set_label(l2);
2003
    tcg_temp_free(t0);
2004 2005 2006
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
2007 2008
#if defined(TARGET_PPC64)
/* sld & sld. */
2009 2010
GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B)
{
2011
    TCGv t0;
2012 2013 2014 2015
    int l1, l2;
    l1 = gen_new_label();
    l2 = gen_new_label();

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

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

/***                       Floating-Point arithmetic                       ***/
2094
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
2095
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
2096
{                                                                             \
2097
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2098
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2099 2100
        return;                                                               \
    }                                                                         \
2101
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2102 2103
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
                     cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
2104
    if (isfloat) {                                                            \
A
aurel32 已提交
2105
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2106
    }                                                                         \
A
aurel32 已提交
2107 2108
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf,                      \
                     Rc(ctx->opcode) != 0);                                   \
2109 2110
}

2111 2112 2113
#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);
2114

2115 2116
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2117
{                                                                             \
2118
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2119
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2120 2121
        return;                                                               \
    }                                                                         \
2122
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2123 2124
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
                     cpu_fpr[rB(ctx->opcode)]);                               \
2125
    if (isfloat) {                                                            \
A
aurel32 已提交
2126
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2127
    }                                                                         \
A
aurel32 已提交
2128 2129
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2130
}
2131 2132 2133
#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);
2134

2135 2136
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2137
{                                                                             \
2138
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2139
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
2140 2141
        return;                                                               \
    }                                                                         \
2142
    gen_reset_fpstatus();                                                     \
A
aurel32 已提交
2143 2144
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
                       cpu_fpr[rC(ctx->opcode)]);                             \
2145
    if (isfloat) {                                                            \
A
aurel32 已提交
2146
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2147
    }                                                                         \
A
aurel32 已提交
2148 2149
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2150
}
2151 2152 2153
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2154

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

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

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

2188
/* fre */
2189
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2190

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

2194
/* frsqrte */
2195 2196 2197
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

/* frsqrtes */
A
aurel32 已提交
2198
GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES)
2199
{
A
aurel32 已提交
2200 2201 2202 2203 2204 2205 2206 2207
    if (unlikely(!ctx->fpu_enabled)) {
        GEN_EXCP_NO_FP(ctx);
        return;
    }
    gen_reset_fpstatus();
    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2208
}
B
bellard 已提交
2209

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

2227
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
B
bellard 已提交
2228
{
2229
    if (unlikely(!ctx->fpu_enabled)) {
2230
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2231 2232
        return;
    }
2233
    gen_reset_fpstatus();
A
aurel32 已提交
2234 2235 2236
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
B
bellard 已提交
2237 2238 2239
}

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

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

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

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

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

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

/* fmr  - fmr. */
2307
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2308 2309
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
{
2310
    if (unlikely(!ctx->fpu_enabled)) {
2311
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2312 2313
        return;
    }
A
aurel32 已提交
2314 2315
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
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);
A
aurel32 已提交
2339
    tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(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
    gen_optimize_fprf();
    gen_reset_fpstatus();
A
aurel32 已提交
2351 2352
    tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
B
bellard 已提交
2353 2354 2355 2356 2357
}

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

2360
    if (unlikely(!ctx->fpu_enabled)) {
2361
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2362 2363
        return;
    }
2364 2365 2366 2367
    crb = 32 - (crbD(ctx->opcode) >> 2);
    gen_optimize_fprf();
    gen_reset_fpstatus();
    if (likely(crb != 30 && crb != 29))
A
aurel32 已提交
2368
        tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(1 << crb));
2369
    if (unlikely(Rc(ctx->opcode) != 0)) {
2370
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2371
    }
B
bellard 已提交
2372 2373 2374 2375 2376
}

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

2379
    if (unlikely(!ctx->fpu_enabled)) {
2380
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2381 2382
        return;
    }
2383 2384 2385 2386
    crb = 32 - (crbD(ctx->opcode) >> 2);
    gen_optimize_fprf();
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
A
aurel32 已提交
2387 2388 2389 2390 2391
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
        TCGv t0 = tcg_const_tl(crb);
        gen_helper_fpscr_setbit(t0);
        tcg_temp_free(t0);
    }
2392
    if (unlikely(Rc(ctx->opcode) != 0)) {
2393
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2394 2395
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2396
    gen_helper_float_check_status();
B
bellard 已提交
2397 2398 2399 2400 2401
}

/* mtfsf */
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
{
A
aurel32 已提交
2402 2403
    TCGv t0;

2404
    if (unlikely(!ctx->fpu_enabled)) {
2405
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2406 2407
        return;
    }
2408 2409
    gen_optimize_fprf();
    gen_reset_fpstatus();
A
aurel32 已提交
2410 2411 2412
    t0 = tcg_const_i32(FM(ctx->opcode));
    gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
    tcg_temp_free(t0);
2413
    if (unlikely(Rc(ctx->opcode) != 0)) {
2414
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2415 2416
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2417
    gen_helper_float_check_status();
B
bellard 已提交
2418 2419 2420 2421 2422
}

/* mtfsfi */
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
{
2423
    int bf, sh;
A
aurel32 已提交
2424
    TCGv t0, t1;
2425

2426
    if (unlikely(!ctx->fpu_enabled)) {
2427
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2428 2429
        return;
    }
2430 2431 2432 2433
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
    gen_optimize_fprf();
    gen_reset_fpstatus();
A
aurel32 已提交
2434 2435 2436 2437 2438
    t0 = tcg_const_tl(FPIMM(ctx->opcode) << (4 * sh));
    t1 = tcg_const_i32(1 << sh);
    gen_helper_store_fpscr(t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
2439
    if (unlikely(Rc(ctx->opcode) != 0)) {
2440
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2441 2442
    }
    /* We can raise a differed exception */
A
aurel32 已提交
2443
    gen_helper_float_check_status();
B
bellard 已提交
2444 2445
}

2446 2447
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2448 2449
static always_inline void gen_addr_imm_index (TCGv EA,
                                              DisasContext *ctx,
2450
                                              target_long maskl)
2451 2452 2453
{
    target_long simm = SIMM(ctx->opcode);

2454
    simm &= ~maskl;
2455 2456 2457 2458 2459 2460
    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)]);
2461 2462
}

2463 2464
static always_inline void gen_addr_reg_index (TCGv EA,
                                              DisasContext *ctx)
2465
{
2466 2467 2468 2469
    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)]);
2470 2471
}

2472 2473
static always_inline void gen_addr_register (TCGv EA,
                                             DisasContext *ctx)
2474
{
2475 2476 2477 2478
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(EA, 0);
    else
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2479 2480
}

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

A
aurel32 已提交
2523 2524 2525 2526 2527 2528 2529 2530

#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 {                                                                       \
P
pbrook 已提交
2531
        TCGv addr = tcg_temp_new();                                   \
A
aurel32 已提交
2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550
        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 {                                                                       \
P
pbrook 已提交
2551
        TCGv addr = tcg_temp_new();                                   \
A
aurel32 已提交
2552 2553 2554 2555 2556 2557 2558 2559 2560 2561
        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)

2562
static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2563
{
2564
    gen_qemu_ld8u_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2565 2566
}

2567
static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2568
{
2569
    gen_qemu_ld8s_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2570 2571
}

2572
static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2573 2574
{
    if (unlikely(flags & 1)) {
P
pbrook 已提交
2575
        TCGv_i32 t0;
2576
        gen_qemu_ld16u_ppc64(arg0, arg1, flags);
P
pbrook 已提交
2577
        t0 = tcg_temp_new_i32();
2578 2579 2580
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap16_i32(t0, t0);
        tcg_gen_extu_i32_tl(arg0, t0);
P
pbrook 已提交
2581
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2582
    } else
2583
        gen_qemu_ld16u_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2584 2585
}

2586
static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2587 2588
{
    if (unlikely(flags & 1)) {
P
pbrook 已提交
2589
        TCGv_i32 t0;
2590
        gen_qemu_ld16u_ppc64(arg0, arg1, flags);
P
pbrook 已提交
2591
        t0 = tcg_temp_new_i32();
2592 2593 2594 2595
        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);
P
pbrook 已提交
2596
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2597
    } else
2598
        gen_qemu_ld16s_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2599 2600
}

2601
static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2602 2603
{
    if (unlikely(flags & 1)) {
P
pbrook 已提交
2604
        TCGv_i32 t0;
2605
        gen_qemu_ld32u_ppc64(arg0, arg1, flags);
P
pbrook 已提交
2606
        t0 = tcg_temp_new_i32();
2607 2608 2609
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap_i32(t0, t0);
        tcg_gen_extu_i32_tl(arg0, t0);
P
pbrook 已提交
2610
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2611
    } else
2612
        gen_qemu_ld32u_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2613 2614
}

2615
static always_inline void gen_qemu_ld32s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2616 2617
{
    if (unlikely(flags & 1)) {
P
pbrook 已提交
2618
        TCGv_i32 t0;
2619
        gen_qemu_ld32u_ppc64(arg0, arg1, flags);
P
pbrook 已提交
2620
        t0 = tcg_temp_new_i32();
2621 2622 2623
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap_i32(t0, t0);
        tcg_gen_ext_i32_tl(arg0, t0);
P
pbrook 已提交
2624
        tcg_temp_free_i32(t0);
A
aurel32 已提交
2625
    } else
2626
        gen_qemu_ld32s_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2627 2628
}

2629
static always_inline void gen_qemu_ld64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2630
{
2631
    gen_qemu_ld64_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2632
    if (unlikely(flags & 1))
2633
        tcg_gen_bswap_i64(arg0, arg0);
A
aurel32 已提交
2634 2635
}

2636
static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2637
{
2638
    gen_qemu_st8_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2639 2640
}

2641
static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2642 2643
{
    if (unlikely(flags & 1)) {
P
pbrook 已提交
2644 2645 2646
        TCGv_i32 t0;
        TCGv_i64 t1;
        t0 = tcg_temp_new_i32();
2647 2648 2649
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_ext16u_i32(t0, t0);
        tcg_gen_bswap16_i32(t0, t0);
P
pbrook 已提交
2650
        t1 = tcg_temp_new_i64();
2651
        tcg_gen_extu_i32_tl(t1, t0);
P
pbrook 已提交
2652
        tcg_temp_free_i32(t0);
2653
        gen_qemu_st16_ppc64(t1, arg1, flags);
P
pbrook 已提交
2654
        tcg_temp_free_i64(t1);
A
aurel32 已提交
2655
    } else
2656
        gen_qemu_st16_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2657 2658
}

2659
static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2660 2661
{
    if (unlikely(flags & 1)) {
P
pbrook 已提交
2662 2663 2664
        TCGv_i32 t0;
        TCGv_i64 t1;
        t0 = tcg_temp_new_i32();
2665 2666
        tcg_gen_trunc_tl_i32(t0, arg0);
        tcg_gen_bswap_i32(t0, t0);
P
pbrook 已提交
2667
        t1 = tcg_temp_new_i64();
2668
        tcg_gen_extu_i32_tl(t1, t0);
P
pbrook 已提交
2669
        tcg_temp_free_i32(t0);
2670
        gen_qemu_st32_ppc64(t1, arg1, flags);
P
pbrook 已提交
2671
        tcg_temp_free_i64(t1);
A
aurel32 已提交
2672
    } else
2673
        gen_qemu_st32_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2674 2675
}

2676
static always_inline void gen_qemu_st64(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2677 2678
{
    if (unlikely(flags & 1)) {
P
pbrook 已提交
2679
        TCGv_i64 t0 = tcg_temp_new_i64();
2680 2681
        tcg_gen_bswap_i64(t0, arg0);
        gen_qemu_st64_ppc64(t0, arg1, flags);
P
pbrook 已提交
2682
        tcg_temp_free_i64(t0);
A
aurel32 已提交
2683
    } else
2684
        gen_qemu_st64_ppc64(arg0, arg1, flags);
A
aurel32 已提交
2685 2686 2687 2688 2689
}


#else /* defined(TARGET_PPC64) */
#define GEN_QEMU_LD_PPC32(width)                                                 \
2690
static always_inline void gen_qemu_ld##width##_ppc32(TCGv arg0, TCGv arg1, int flags)\
A
aurel32 已提交
2691
{                                                                                \
2692
    tcg_gen_qemu_ld##width(arg0, arg1, flags >> 1);                                  \
A
aurel32 已提交
2693 2694 2695 2696 2697 2698 2699 2700 2701
}
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)

#define GEN_QEMU_ST_PPC32(width)                                                 \
2702
static always_inline void gen_qemu_st##width##_ppc32(TCGv arg0, TCGv arg1, int flags)\
A
aurel32 已提交
2703
{                                                                                \
2704
    tcg_gen_qemu_st##width(arg0, arg1, flags >> 1);                                  \
A
aurel32 已提交
2705 2706 2707 2708 2709
}
GEN_QEMU_ST_PPC32(8)
GEN_QEMU_ST_PPC32(16)
GEN_QEMU_ST_PPC32(32)

2710
static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2711
{
2712
    gen_qemu_ld8u_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2713 2714
}

2715
static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2716
{
2717
    gen_qemu_ld8s_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2718 2719
}

2720
static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2721
{
2722
    gen_qemu_ld16u_ppc32(arg0, arg1, flags >> 1);
A
aurel32 已提交
2723
    if (unlikely(flags & 1))
2724
        tcg_gen_bswap16_i32(arg0, arg0);
A
aurel32 已提交
2725 2726
}

2727
static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2728 2729
{
    if (unlikely(flags & 1)) {
2730 2731 2732
        gen_qemu_ld16u_ppc32(arg0, arg1, flags);
        tcg_gen_bswap16_i32(arg0, arg0);
        tcg_gen_ext16s_i32(arg0, arg0);
A
aurel32 已提交
2733
    } else
2734
        gen_qemu_ld16s_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2735 2736
}

2737
static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2738
{
2739
    gen_qemu_ld32u_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2740
    if (unlikely(flags & 1))
2741
        tcg_gen_bswap_i32(arg0, arg0);
A
aurel32 已提交
2742 2743
}

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

2749
static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2750 2751
{
    if (unlikely(flags & 1)) {
P
pbrook 已提交
2752
        TCGv_i32 temp = tcg_temp_new_i32();
2753
        tcg_gen_ext16u_i32(temp, arg0);
A
aurel32 已提交
2754
        tcg_gen_bswap16_i32(temp, temp);
2755
        gen_qemu_st16_ppc32(temp, arg1, flags);
P
pbrook 已提交
2756
        tcg_temp_free_i32(temp);
A
aurel32 已提交
2757
    } else
2758
        gen_qemu_st16_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2759 2760
}

2761
static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags)
A
aurel32 已提交
2762 2763
{
    if (unlikely(flags & 1)) {
P
pbrook 已提交
2764
        TCGv_i32 temp = tcg_temp_new_i32();
2765
        tcg_gen_bswap_i32(temp, arg0);
2766
        gen_qemu_st32_ppc32(temp, arg1, flags);
P
pbrook 已提交
2767
        tcg_temp_free_i32(temp);
A
aurel32 已提交
2768
    } else
2769
        gen_qemu_st32_ppc32(arg0, arg1, flags);
A
aurel32 已提交
2770 2771 2772 2773
}

#endif

2774 2775
#define GEN_LD(width, opc, type)                                              \
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
B
bellard 已提交
2776
{                                                                             \
P
pbrook 已提交
2777
    TCGv EA = tcg_temp_new();                                      \
A
aurel32 已提交
2778 2779 2780
    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 已提交
2781 2782
}

2783 2784
#define GEN_LDU(width, opc, type)                                             \
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
B
bellard 已提交
2785
{                                                                             \
A
aurel32 已提交
2786
    TCGv EA;                                                                  \
2787 2788
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2789
        GEN_EXCP_INVAL(ctx);                                                  \
2790
        return;                                                               \
2791
    }                                                                         \
P
pbrook 已提交
2792
    EA = tcg_temp_new();                                           \
J
j_mayer 已提交
2793
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2794
        gen_addr_imm_index(EA, ctx, 0x03);                                    \
J
j_mayer 已提交
2795
    else                                                                      \
A
aurel32 已提交
2796 2797 2798 2799
        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 已提交
2800 2801
}

2802 2803
#define GEN_LDUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2804
{                                                                             \
A
aurel32 已提交
2805
    TCGv EA;                                                                  \
2806 2807
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2808
        GEN_EXCP_INVAL(ctx);                                                  \
2809
        return;                                                               \
2810
    }                                                                         \
P
pbrook 已提交
2811
    EA = tcg_temp_new();                                           \
A
aurel32 已提交
2812 2813 2814 2815
    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 已提交
2816 2817
}

2818 2819
#define GEN_LDX(width, opc2, opc3, type)                                      \
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
B
bellard 已提交
2820
{                                                                             \
P
pbrook 已提交
2821
    TCGv EA = tcg_temp_new();                                      \
A
aurel32 已提交
2822 2823 2824
    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 已提交
2825 2826
}

2827 2828 2829 2830 2831
#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 已提交
2832 2833

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

    /* 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;
    }
P
pbrook 已提交
2898
    EA = tcg_temp_new();
A
aurel32 已提交
2899 2900 2901 2902 2903
    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);
2904 2905
#endif
}
2906
#endif
B
bellard 已提交
2907 2908

/***                              Integer store                            ***/
2909 2910
#define GEN_ST(width, opc, type)                                              \
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
B
bellard 已提交
2911
{                                                                             \
P
pbrook 已提交
2912
    TCGv EA = tcg_temp_new();                                      \
A
aurel32 已提交
2913 2914 2915
    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 已提交
2916 2917
}

2918 2919
#define GEN_STU(width, opc, type)                                             \
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
B
bellard 已提交
2920
{                                                                             \
A
aurel32 已提交
2921
    TCGv EA;                                                                  \
2922
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2923
        GEN_EXCP_INVAL(ctx);                                                  \
2924
        return;                                                               \
2925
    }                                                                         \
P
pbrook 已提交
2926
    EA = tcg_temp_new();                                           \
J
j_mayer 已提交
2927
    if (type == PPC_64B)                                                      \
A
aurel32 已提交
2928
        gen_addr_imm_index(EA, ctx, 0x03);                                    \
J
j_mayer 已提交
2929
    else                                                                      \
A
aurel32 已提交
2930 2931 2932 2933
        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 已提交
2934 2935
}

2936 2937
#define GEN_STUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                \
B
bellard 已提交
2938
{                                                                             \
A
aurel32 已提交
2939
    TCGv EA;                                                                  \
2940
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2941
        GEN_EXCP_INVAL(ctx);                                                  \
2942
        return;                                                               \
2943
    }                                                                         \
P
pbrook 已提交
2944
    EA = tcg_temp_new();                                           \
A
aurel32 已提交
2945 2946 2947 2948
    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 已提交
2949 2950
}

2951 2952
#define GEN_STX(width, opc2, opc3, type)                                      \
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2953
{                                                                             \
P
pbrook 已提交
2954
    TCGv EA = tcg_temp_new();                                      \
A
aurel32 已提交
2955 2956 2957
    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 已提交
2958 2959
}

2960 2961 2962 2963 2964
#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 已提交
2965 2966

/* stb stbu stbux stbx */
A
aurel32 已提交
2967
GEN_STS(8, 0x06, PPC_INTEGER);
B
bellard 已提交
2968
/* sth sthu sthux sthx */
A
aurel32 已提交
2969
GEN_STS(16, 0x0C, PPC_INTEGER);
B
bellard 已提交
2970
/* stw stwu stwux stwx */
A
aurel32 已提交
2971
GEN_STS(32, 0x04, PPC_INTEGER);
2972
#if defined(TARGET_PPC64)
A
aurel32 已提交
2973 2974
GEN_STUX(64, 0x15, 0x05, PPC_64B);
GEN_STX(64, 0x15, 0x04, PPC_64B);
2975
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2976
{
2977
    int rs;
A
aurel32 已提交
2978
    TCGv EA;
2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990

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

B
bellard 已提交
3036
/* lwbrx */
A
aurel32 已提交
3037 3038
void always_inline gen_qemu_ld32ur(TCGv t0, TCGv t1, int flags)
{
P
pbrook 已提交
3039 3040 3041
    TCGv_i32 temp = tcg_temp_new_i32();
    gen_qemu_ld32u(t0, t1, flags);
    tcg_gen_trunc_tl_i32(temp, t0);
A
aurel32 已提交
3042 3043
    tcg_gen_bswap_i32(temp, temp);
    tcg_gen_extu_i32_tl(t0, temp);
P
pbrook 已提交
3044
    tcg_temp_free_i32(temp);
A
aurel32 已提交
3045 3046 3047
}
GEN_LDX(32ur, 0x16, 0x10, PPC_INTEGER);

B
bellard 已提交
3048
/* sthbrx */
A
aurel32 已提交
3049 3050
void always_inline gen_qemu_st16r(TCGv t0, TCGv t1, int flags)
{
P
pbrook 已提交
3051 3052
    TCGv_i32 temp = tcg_temp_new_i32();
    TCGv t2 = tcg_temp_new();
A
aurel32 已提交
3053 3054 3055
    tcg_gen_trunc_tl_i32(temp, t0);
    tcg_gen_ext16u_i32(temp, temp);
    tcg_gen_bswap16_i32(temp, temp);
P
pbrook 已提交
3056 3057 3058 3059
    tcg_gen_extu_i32_tl(t2, temp);
    tcg_temp_free_i32(temp);
    gen_qemu_st16(t2, t1, flags);
    tcg_temp_free(t2);
A
aurel32 已提交
3060 3061 3062
}
GEN_STX(16r, 0x16, 0x1C, PPC_INTEGER);

B
bellard 已提交
3063
/* stwbrx */
A
aurel32 已提交
3064 3065
void always_inline gen_qemu_st32r(TCGv t0, TCGv t1, int flags)
{
P
pbrook 已提交
3066 3067
    TCGv_i32 temp = tcg_temp_new_i32();
    TCGv t2 = tcg_temp_new();
A
aurel32 已提交
3068 3069
    tcg_gen_trunc_tl_i32(temp, t0);
    tcg_gen_bswap_i32(temp, temp);
P
pbrook 已提交
3070 3071
    tcg_gen_extu_i32_tl(t2, temp);
    tcg_temp_free_i32(temp);
3072
    gen_qemu_st32(t2, t1, flags);
P
pbrook 已提交
3073
    tcg_temp_free(t2);
A
aurel32 已提交
3074 3075
}
GEN_STX(32r, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
3076 3077

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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
        }
P
pbrook 已提交
3566
        tcg_temp_free_i32(temp);
3567
    }
3568
    if (type == BCOND_IM) {
3569 3570 3571 3572 3573 3574
        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 已提交
3575
        gen_set_label(l1);
3576
        gen_goto_tb(ctx, 1, ctx->nip);
3577
    } else {
3578
#if defined(TARGET_PPC64)
3579 3580 3581 3582 3583 3584 3585 3586 3587 3588
        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);
3589 3590
        else
#endif
3591
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
B
bellard 已提交
3592
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3593
    }
3594 3595 3596
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3885 3886
    crm = CRM(ctx->opcode);
    if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
P
pbrook 已提交
3887
        TCGv_i32 temp = tcg_temp_new_i32();
3888
        crn = ffs(crm);
P
pbrook 已提交
3889 3890
        tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
        tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
3891
        tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
P
pbrook 已提交
3892
        tcg_temp_free_i32(temp);
3893
    } else {
P
pbrook 已提交
3894 3895 3896
        TCGv_i32 temp = tcg_const_i32(crm);
        gen_helper_store_cr(cpu_gpr[rS(ctx->opcode)], temp);
        tcg_temp_free_i32(temp);
3897
    }
B
bellard 已提交
3898 3899 3900
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4572
    gen_addr_reg_index(cpu_T[0], ctx);
4573 4574 4575 4576
    if (ra == 0) {
        ra = rb;
    }
    /* NIP cannot be restored if the memory exception comes from an helper */
4577
    gen_update_nip(ctx, ctx->nip - 4);
A
aurel32 已提交
4578 4579 4580
    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);
4581
    op_POWER_lscbx(rD(ctx->opcode), ra, rb);
A
aurel32 已提交
4582 4583
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
    tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]);
4584
    if (unlikely(Rc(ctx->opcode) != 0))
4585
        gen_set_Rc0(ctx, cpu_T[0]);
4586 4587 4588 4589 4590
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/* PowerPC 602 specific instructions */
/* dsa  */
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4852
    GEN_EXCP_INVAL(ctx);
4853 4854 4855 4856 4857 4858
}

/* esa */
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4859
    GEN_EXCP_INVAL(ctx);
4860 4861 4862 4863 4864 4865
}

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

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

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

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

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

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

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

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

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

/* svc is not implemented for now */

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

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

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

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

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

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

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

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

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

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

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

P
pbrook 已提交
5186 5187
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
5188

5189 5190 5191 5192 5193 5194 5195
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
5196 5197 5198
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16s_tl(t1, t1);
5199 5200 5201 5202 5203
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
5204 5205 5206
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
        tcg_gen_ext16u_tl(t1, t1);
5207 5208 5209 5210 5211 5212 5213
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
5214 5215 5216 5217
        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);
5218 5219 5220 5221 5222
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
5223 5224 5225 5226
        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);
5227 5228 5229 5230 5231 5232 5233
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
5234 5235
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5236 5237 5238 5239 5240
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
5241 5242
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5243 5244 5245
        break;
    }
    if (opc2 & 0x04) {
5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269
        /* (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 已提交
5270
                if (opc3 & 0x02) {
5271 5272 5273 5274 5275 5276 5277
                    /* 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 已提交
5278
                if (opc3 & 0x02) {
5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291
                    /* 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);
5292
    }
5293 5294
    tcg_temp_free(t0);
    tcg_temp_free(t1);
5295 5296
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
5297
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5298 5299 5300
    }
}

5301 5302
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)                  \
5303 5304 5305 5306 5307 5308
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

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

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

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

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

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

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

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

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

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

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

/* dcread */
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
5502
    GEN_EXCP_PRIVOPC(ctx);
5503
#else
A
aurel32 已提交
5504
    TCGv EA, val;
5505
    if (unlikely(!ctx->supervisor)) {
5506
        GEN_EXCP_PRIVOPC(ctx);
5507 5508
        return;
    }
P
pbrook 已提交
5509
    EA = tcg_temp_new();
A
aurel32 已提交
5510
    gen_addr_reg_index(EA, ctx);
P
pbrook 已提交
5511
    val = tcg_temp_new();
A
aurel32 已提交
5512 5513 5514 5515
    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);
5516 5517 5518 5519
#endif
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/* msync replaces sync on 440 */
5826
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
5827 5828 5829 5830 5831
{
    /* interpreted as no-op */
}

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

5840 5841 5842
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */

5843 5844 5845 5846 5847 5848 5849 5850 5851
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]);
}
5852 5853 5854

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

#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;                                                               \
    }                                                                         \
5870
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
5871
    op_vr_ldst(vr_l##name);                                                   \
5872
    gen_store_avr(rD(ctx->opcode), 0);                                        \
5873 5874 5875 5876 5877 5878 5879 5880 5881
}

#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;                                                               \
    }                                                                         \
5882
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
5883
    gen_load_avr(0, rS(ctx->opcode));                                         \
5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898
    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);

5899 5900
/***                           SPE extension                               ***/
/* Register moves */
5901

P
pbrook 已提交
5902
static always_inline void gen_load_gpr64(TCGv_i64 t, int reg) {
A
aurel32 已提交
5903 5904 5905
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
#else
P
pbrook 已提交
5906
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
5907
#endif
A
aurel32 已提交
5908
}
5909

P
pbrook 已提交
5910
static always_inline void gen_store_gpr64(int reg, TCGv_i64 t) {
A
aurel32 已提交
5911 5912 5913
#if defined(TARGET_PPC64)
    tcg_gen_mov_i64(cpu_gpr[reg], t);
#else
P
pbrook 已提交
5914
    TCGv_i64 tmp = tcg_temp_new_i64();
A
aurel32 已提交
5915 5916 5917
    tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
    tcg_gen_shri_i64(tmp, t, 32);
    tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
P
pbrook 已提交
5918
    tcg_temp_free_i64(tmp);
5919
#endif
A
aurel32 已提交
5920
}
5921

5922 5923 5924 5925 5926 5927 5928 5929 5930 5931
#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 */
5932
static always_inline void gen_speundef (DisasContext *ctx)
5933
{
5934
    GEN_EXCP_INVAL(ctx);
5935 5936 5937
}

/* SPE load and stores */
5938
static always_inline void gen_addr_spe_imm_index (TCGv EA, DisasContext *ctx, int sh)
5939 5940 5941
{
    target_long simm = rB(ctx->opcode);

5942 5943 5944 5945 5946 5947
    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)]);
5948 5949 5950 5951
}

#define op_spe_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_SPE_LD_TABLE(name)                                                 \
5952 5953
static GenOpFunc *gen_op_spe_l##name[NB_MEM_FUNCS] = {                        \
    GEN_MEM_FUNCS(spe_l##name),                                               \
5954 5955
};
#define OP_SPE_ST_TABLE(name)                                                 \
5956 5957
static GenOpFunc *gen_op_spe_st##name[NB_MEM_FUNCS] = {                       \
    GEN_MEM_FUNCS(spe_st##name),                                              \
5958
};
5959 5960

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

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

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

#define GEN_SPE_STX(name)                                                     \
6002
static always_inline void gen_evst##name##x (DisasContext *ctx)               \
6003 6004
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6005
        GEN_EXCP_NO_AP(ctx);                                                  \
6006 6007
        return;                                                               \
    }                                                                         \
6008
    gen_addr_reg_index(cpu_T[0], ctx);                                        \
A
aurel32 已提交
6009
    gen_load_gpr64(cpu_T64[1], rS(ctx->opcode));                              \
6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021
    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)

6022 6023 6024
/* SPE logic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
6025
static always_inline void gen_##name (DisasContext *ctx)                      \
6026 6027
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6028
        GEN_EXCP_NO_AP(ctx);                                                  \
6029 6030
        return;                                                               \
    }                                                                         \
6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
           cpu_gpr[rB(ctx->opcode)]);                                         \
}
#else
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
           cpu_gpr[rB(ctx->opcode)]);                                         \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
           cpu_gprh[rB(ctx->opcode)]);                                        \
6046
}
6047 6048 6049 6050 6051 6052 6053 6054 6055 6056
#endif

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

6058 6059 6060
/* SPE logic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
6061 6062 6063 6064 6065 6066
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6067 6068 6069
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6070 6071 6072 6073
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_opi(t0, t0, rB(ctx->opcode));                                         \
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
6074
    tcg_temp_free_i64(t2);                                                    \
6075 6076
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6077 6078
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6079
}
6080 6081
#else
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
6082
static always_inline void gen_##name (DisasContext *ctx)                      \
6083 6084
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6085
        GEN_EXCP_NO_AP(ctx);                                                  \
6086 6087
        return;                                                               \
    }                                                                         \
6088 6089 6090 6091
    tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],               \
            rB(ctx->opcode));                                                 \
    tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],             \
            rB(ctx->opcode));                                                 \
6092
}
6093 6094 6095 6096 6097
#endif
GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
6098

6099 6100 6101
/* SPE arithmetic */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6102
static always_inline void gen_##name (DisasContext *ctx)                      \
6103 6104
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6105
        GEN_EXCP_NO_AP(ctx);                                                  \
6106 6107
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6108 6109 6110
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6111 6112 6113 6114
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_op(t0, t0);                                                           \
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
6115
    tcg_temp_free_i64(t2);                                                    \
6116 6117
    tcg_op(t1, t1);                                                           \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6118 6119
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6120
}
6121
#else
P
pbrook 已提交
6122
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6123 6124 6125 6126 6127 6128 6129 6130 6131 6132
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);               \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);             \
}
#endif
6133

P
pbrook 已提交
6134
static always_inline void gen_op_evabs (TCGv_i32 ret, TCGv_i32 arg1)
6135 6136 6137
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
6138

6139 6140 6141 6142
    tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
    tcg_gen_neg_i32(ret, arg1);
    tcg_gen_br(l2);
    gen_set_label(l1);
P
pbrook 已提交
6143
    tcg_gen_mov_i32(ret, arg1);
6144 6145 6146 6147 6148 6149
    gen_set_label(l2);
}
GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
P
pbrook 已提交
6150
static always_inline void gen_op_evrndw (TCGv_i32 ret, TCGv_i32 arg1)
6151
{
6152 6153 6154 6155
    tcg_gen_addi_i32(ret, arg1, 0x8000);
    tcg_gen_ext16u_i32(ret, ret);
}
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
P
pbrook 已提交
6156 6157
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6158

6159 6160 6161
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
static always_inline void gen_##name (DisasContext *ctx)                      \
6162 6163
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6164
        GEN_EXCP_NO_AP(ctx);                                                  \
6165 6166
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6167 6168 6169 6170
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t3 = tcg_temp_local_new(TCG_TYPE_I64);                           \
6171 6172 6173 6174 6175 6176 6177
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]);                      \
    tcg_op(t0, t0, t2);                                                       \
    tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t3);                                            \
    tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t2, t3);                                            \
P
pbrook 已提交
6178
    tcg_temp_free_i64(t3);                                                    \
6179
    tcg_op(t1, t1, t2);                                                       \
P
pbrook 已提交
6180
    tcg_temp_free_i32(t2);                                                    \
6181
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6182 6183
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6184
}
6185 6186 6187
#else
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
static always_inline void gen_##name (DisasContext *ctx)                      \
6188 6189
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
6190
        GEN_EXCP_NO_AP(ctx);                                                  \
6191 6192
        return;                                                               \
    }                                                                         \
6193 6194 6195 6196
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
           cpu_gpr[rB(ctx->opcode)]);                                         \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
           cpu_gprh[rB(ctx->opcode)]);                                        \
6197
}
6198
#endif
6199

P
pbrook 已提交
6200
static always_inline void gen_op_evsrwu (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6201
{
P
pbrook 已提交
6202
    TCGv_i32 t0;
6203
    int l1, l2;
6204

6205 6206
    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6207
    t0 = tcg_temp_local_new_i32();
6208 6209 6210 6211 6212 6213 6214 6215
    /* No error here: 6 bits are used */
    tcg_gen_andi_i32(t0, arg2, 0x3F);
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
    tcg_gen_shr_i32(ret, arg1, t0);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_i32(ret, 0);
    tcg_gen_br(l2);
P
pbrook 已提交
6216
    tcg_temp_free_i32(t0);
6217 6218
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
P
pbrook 已提交
6219
static always_inline void gen_op_evsrws (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6220
{
P
pbrook 已提交
6221
    TCGv_i32 t0;
6222 6223 6224 6225
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6226
    t0 = tcg_temp_local_new_i32();
6227 6228 6229 6230 6231 6232 6233 6234
    /* No error here: 6 bits are used */
    tcg_gen_andi_i32(t0, arg2, 0x3F);
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
    tcg_gen_sar_i32(ret, arg1, t0);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_i32(ret, 0);
    tcg_gen_br(l2);
P
pbrook 已提交
6235
    tcg_temp_free_i32(t0);
6236 6237
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
P
pbrook 已提交
6238
static always_inline void gen_op_evslw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6239
{
P
pbrook 已提交
6240
    TCGv_i32 t0;
6241 6242 6243 6244
    int l1, l2;

    l1 = gen_new_label();
    l2 = gen_new_label();
P
pbrook 已提交
6245
    t0 = tcg_temp_local_new_i32();
6246 6247 6248 6249 6250 6251 6252 6253
    /* No error here: 6 bits are used */
    tcg_gen_andi_i32(t0, arg2, 0x3F);
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
    tcg_gen_shl_i32(ret, arg1, t0);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_i32(ret, 0);
    tcg_gen_br(l2);
P
pbrook 已提交
6254
    tcg_temp_free_i32(t0);
6255 6256
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
P
pbrook 已提交
6257
static always_inline void gen_op_evrlw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6258
{
P
pbrook 已提交
6259
    TCGv_i32 t0 = tcg_temp_new_i32();
6260 6261
    tcg_gen_andi_i32(t0, arg2, 0x1F);
    tcg_gen_rotl_i32(ret, arg1, t0);
P
pbrook 已提交
6262
    tcg_temp_free_i32(t0);
6263 6264 6265 6266 6267 6268 6269 6270 6271
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
static always_inline void gen_evmergehi (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
        GEN_EXCP_NO_AP(ctx);
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6272 6273
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
}
GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
P
pbrook 已提交
6285
static always_inline void gen_op_evsubf (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6286
{
6287 6288 6289
    tcg_gen_sub_i32(ret, arg2, arg1);
}
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
6290

6291 6292 6293 6294 6295 6296 6297 6298 6299
/* SPE arithmetic immediate */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
P
pbrook 已提交
6300 6301 6302
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6303 6304 6305 6306
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]);                      \
    tcg_op(t0, t0, rA(ctx->opcode));                                          \
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
6307
    tcg_temp_free_i64(t2);                                                        \
6308 6309
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
P
pbrook 已提交
6310 6311
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342
}
#else
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],                \
           rA(ctx->opcode));                                                  \
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)],              \
           rA(ctx->opcode));                                                  \
}
#endif
GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);

/* SPE comparison */
#if defined(TARGET_PPC64)
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
P
pbrook 已提交
6343 6344 6345
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6346 6347 6348
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]);                      \
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l1);                                 \
P
pbrook 已提交
6349
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
6350 6351 6352 6353 6354 6355 6356 6357 6358
    tcg_gen_br(l2);                                                           \
    gen_set_label(l1);                                                        \
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
    gen_set_label(l2);                                                        \
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t0, t2);                                            \
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
P
pbrook 已提交
6359
    tcg_temp_free_i64(t2);                                                    \
6360 6361 6362 6363 6364 6365 6366 6367
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l3);                                 \
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
    tcg_gen_br(l4);                                                           \
    gen_set_label(l3);                                                        \
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
                    CRF_CH | CRF_CH_OR_CL);                                   \
    gen_set_label(l4);                                                        \
P
pbrook 已提交
6368 6369
    tcg_temp_free_i32(t0);                                                    \
    tcg_temp_free_i32(t1);                                                    \
6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 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
}
#else
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    int l1 = gen_new_label();                                                 \
    int l2 = gen_new_label();                                                 \
    int l3 = gen_new_label();                                                 \
    int l4 = gen_new_label();                                                 \
                                                                              \
    tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)],                    \
                       cpu_gpr[rB(ctx->opcode)], l1);                         \
    tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0);                           \
    tcg_gen_br(l2);                                                           \
    gen_set_label(l1);                                                        \
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
    gen_set_label(l2);                                                        \
    tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)],                   \
                       cpu_gprh[rB(ctx->opcode)], l3);                        \
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
    tcg_gen_br(l4);                                                           \
    gen_set_label(l3);                                                        \
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
                    CRF_CH | CRF_CH_OR_CL);                                   \
    gen_set_label(l4);                                                        \
}
#endif
GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);

/* SPE misc */
static always_inline void gen_brinc (DisasContext *ctx)
{
    /* Note: brinc is usable even if SPE is disabled */
P
pbrook 已提交
6413 6414
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6415
}
6416 6417 6418 6419 6420 6421 6422
static always_inline void gen_evmergelo (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
        GEN_EXCP_NO_AP(ctx);
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6423 6424
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
#endif
}
static always_inline void gen_evmergehilo (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
        GEN_EXCP_NO_AP(ctx);
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6442 6443
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
}
static always_inline void gen_evmergelohi (DisasContext *ctx)
{
    if (unlikely(!ctx->spe_enabled)) {
        GEN_EXCP_NO_AP(ctx);
        return;
    }
#if defined(TARGET_PPC64)
P
pbrook 已提交
6461 6462
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
#endif
}
static always_inline void gen_evsplati (DisasContext *ctx)
{
    int32_t imm = (int32_t)(rA(ctx->opcode) << 11) >> 27;
6476

6477
#if defined(TARGET_PPC64)
P
pbrook 已提交
6478 6479
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6480 6481 6482 6483 6484 6485 6486 6487 6488 6489
    tcg_gen_movi_tl(t0, imm);
    tcg_gen_shri_tl(t1, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
}
6490
static always_inline void gen_evsplatfi (DisasContext *ctx)
6491
{
6492
    uint32_t imm = rA(ctx->opcode) << 11;
6493

6494
#if defined(TARGET_PPC64)
P
pbrook 已提交
6495 6496
    TCGv t0 = tcg_temp_new();
    TCGv t1 = tcg_temp_new();
6497 6498 6499 6500 6501 6502 6503 6504 6505
    tcg_gen_movi_tl(t0, imm);
    tcg_gen_shri_tl(t1, t0, 32);
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
    tcg_temp_free(t0);
    tcg_temp_free(t1);
#else
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
#endif
6506 6507
}

6508 6509 6510 6511 6512 6513
static always_inline void gen_evsel (DisasContext *ctx)
{
    int l1 = gen_new_label();
    int l2 = gen_new_label();
    int l3 = gen_new_label();
    int l4 = gen_new_label();
P
pbrook 已提交
6514
    TCGv_i32 t0 = tcg_temp_local_new_i32();
6515
#if defined(TARGET_PPC64)
P
pbrook 已提交
6516 6517
    TCGv t1 = tcg_temp_local_new();
    TCGv t2 = tcg_temp_local_new();
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
#endif
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
#endif
    tcg_gen_br(l2);
    gen_set_label(l1);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
#else
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
#endif
    gen_set_label(l2);
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
#endif
    tcg_gen_br(l4);
    gen_set_label(l3);
#if defined(TARGET_PPC64)
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
#else
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
#endif
    gen_set_label(l4);
P
pbrook 已提交
6549
    tcg_temp_free_i32(t0);
6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571
#if defined(TARGET_PPC64)
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
    tcg_temp_free(t1);
    tcg_temp_free(t2);
#endif
}
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
{
    gen_evsel(ctx);
}
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
{
    gen_evsel(ctx);
}
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
{
    gen_evsel(ctx);
}
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
{
    gen_evsel(ctx);
}
6572 6573 6574 6575 6576 6577 6578 6579 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

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

/* 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)                                             \
6609
static always_inline void gen_op_spe_stwwe_##suffix (void)                    \
6610 6611 6612 6613 6614
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_##suffix();                                              \
}
#define _GEN_OP_SPE_STWWE_LE(suffix)                                          \
6615
static always_inline void gen_op_spe_stwwe_le_##suffix (void)                 \
6616 6617 6618 6619 6620 6621 6622 6623
{                                                                             \
    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);                                                 \
6624
static always_inline void gen_op_spe_stwwe_64_##suffix (void)                 \
6625 6626 6627 6628
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_64_##suffix();                                           \
}                                                                             \
6629
static always_inline void gen_op_spe_stwwe_le_64_##suffix (void)              \
6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642
{                                                                             \
    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);
6643 6644
GEN_OP_SPE_STWWE(kernel);
GEN_OP_SPE_STWWE(hypv);
6645 6646 6647 6648 6649
#endif /* defined(CONFIG_USER_ONLY) */
GEN_SPEOP_ST(wwe, 2);
GEN_SPEOP_ST(wwo, 2);

#define GEN_SPE_LDSPLAT(name, op, suffix)                                     \
6650
static always_inline void gen_op_spe_l##name##_##suffix (void)                \
6651 6652 6653 6654 6655 6656
{                                                                             \
    gen_op_##op##_##suffix();                                                 \
    gen_op_splatw_T1_64();                                                    \
}

#define GEN_OP_SPE_LHE(suffix)                                                \
6657
static always_inline void gen_op_spe_lhe_##suffix (void)                      \
6658 6659 6660 6661 6662 6663
{                                                                             \
    gen_op_spe_lh_##suffix();                                                 \
    gen_op_sli16_T1_64();                                                     \
}

#define GEN_OP_SPE_LHX(suffix)                                                \
6664
static always_inline void gen_op_spe_lhx_##suffix (void)                      \
6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694
{                                                                             \
    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);
6695 6696
GEN_OP_SPE_LHE(kernel);
GEN_OP_SPE_LHE(hypv);
6697
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
6698 6699
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, hypv);
6700
GEN_OP_SPE_LHE(le_user);
6701 6702
GEN_OP_SPE_LHE(le_kernel);
GEN_OP_SPE_LHE(le_hypv);
6703
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
6704 6705
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_hypv);
6706
GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
6707 6708
GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, hypv);
6709
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
6710 6711
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_hypv);
6712
GEN_OP_SPE_LHX(user);
6713 6714
GEN_OP_SPE_LHX(kernel);
GEN_OP_SPE_LHX(hypv);
6715
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
6716 6717
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, hypv);
6718
GEN_OP_SPE_LHX(le_user);
6719 6720
GEN_OP_SPE_LHX(le_kernel);
GEN_OP_SPE_LHX(le_hypv);
6721
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
6722 6723
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_hypv);
6724 6725
#if defined(TARGET_PPC64)
GEN_OP_SPE_LHE(64_user);
6726 6727
GEN_OP_SPE_LHE(64_kernel);
GEN_OP_SPE_LHE(64_hypv);
6728
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
6729 6730
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_hypv);
6731
GEN_OP_SPE_LHE(le_64_user);
6732 6733
GEN_OP_SPE_LHE(le_64_kernel);
GEN_OP_SPE_LHE(le_64_hypv);
6734
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
6735 6736
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_hypv);
6737
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
6738 6739
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_hypv);
6740
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
6741 6742
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_hypv);
6743
GEN_OP_SPE_LHX(64_user);
6744 6745
GEN_OP_SPE_LHX(64_kernel);
GEN_OP_SPE_LHX(64_hypv);
6746
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
6747 6748
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_hypv);
6749
GEN_OP_SPE_LHX(le_64_user);
6750 6751
GEN_OP_SPE_LHX(le_64_kernel);
GEN_OP_SPE_LHX(le_64_hypv);
6752
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
6753 6754
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_hypv);
6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859
#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)                                               \
6860
static always_inline void gen_##name (DisasContext *ctx)                      \
6861
{                                                                             \
A
aurel32 已提交
6862
    gen_load_gpr64(cpu_T64[0], rB(ctx->opcode));                              \
6863
    gen_op_##name();                                                          \
A
aurel32 已提交
6864
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6865 6866
}

6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894
#define GEN_SPEFPUOP_ARITH1(name)                                             \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
    gen_op_##name();                                                          \
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
}

#define GEN_SPEFPUOP_ARITH2(name)                                             \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
    gen_op_##name();                                                          \
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
}

#define GEN_SPEFPUOP_COMP(name)                                               \
static always_inline void gen_##name (DisasContext *ctx)                      \
{                                                                             \
P
pbrook 已提交
6895
    TCGv_i32 crf = cpu_crf[crfD(ctx->opcode)];                                \
6896 6897 6898 6899 6900 6901 6902
    if (unlikely(!ctx->spe_enabled)) {                                        \
        GEN_EXCP_NO_AP(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
    gen_op_##name();                                                          \
P
pbrook 已提交
6903 6904
    tcg_gen_trunc_tl_i32(crf, cpu_T[0]);                                      \
    tcg_gen_andi_i32(crf, crf, 0xf);                                          \
6905 6906
}

6907 6908
/* Single precision floating-point vectors operations */
/* Arithmetic */
6909 6910 6911 6912 6913 6914 6915
GEN_SPEFPUOP_ARITH2(evfsadd);
GEN_SPEFPUOP_ARITH2(evfssub);
GEN_SPEFPUOP_ARITH2(evfsmul);
GEN_SPEFPUOP_ARITH2(evfsdiv);
GEN_SPEFPUOP_ARITH1(evfsabs);
GEN_SPEFPUOP_ARITH1(evfsnabs);
GEN_SPEFPUOP_ARITH1(evfsneg);
6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927
/* 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 */
6928 6929 6930 6931 6932 6933
GEN_SPEFPUOP_COMP(evfscmpgt);
GEN_SPEFPUOP_COMP(evfscmplt);
GEN_SPEFPUOP_COMP(evfscmpeq);
GEN_SPEFPUOP_COMP(evfststgt);
GEN_SPEFPUOP_COMP(evfststlt);
GEN_SPEFPUOP_COMP(evfststeq);
6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952

/* 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 */
6953 6954 6955 6956 6957 6958 6959
GEN_SPEFPUOP_ARITH2(efsadd);
GEN_SPEFPUOP_ARITH2(efssub);
GEN_SPEFPUOP_ARITH2(efsmul);
GEN_SPEFPUOP_ARITH2(efsdiv);
GEN_SPEFPUOP_ARITH1(efsabs);
GEN_SPEFPUOP_ARITH1(efsnabs);
GEN_SPEFPUOP_ARITH1(efsneg);
6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972
/* 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 */
6973 6974 6975 6976 6977 6978
GEN_SPEFPUOP_COMP(efscmpgt);
GEN_SPEFPUOP_COMP(efscmplt);
GEN_SPEFPUOP_COMP(efscmpeq);
GEN_SPEFPUOP_COMP(efststgt);
GEN_SPEFPUOP_COMP(efststlt);
GEN_SPEFPUOP_COMP(efststeq);
6979 6980

/* Opcodes definitions */
6981
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
6982 6983 6984 6985 6986 6987 6988 6989 6990
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); //
6991 6992
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
6993 6994 6995 6996 6997
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //

/* Double precision floating-point operations */
/* Arithmetic */
6998 6999 7000 7001 7002 7003 7004
GEN_SPEFPUOP_ARITH2(efdadd);
GEN_SPEFPUOP_ARITH2(efdsub);
GEN_SPEFPUOP_ARITH2(efdmul);
GEN_SPEFPUOP_ARITH2(efddiv);
GEN_SPEFPUOP_ARITH1(efdabs);
GEN_SPEFPUOP_ARITH1(efdnabs);
GEN_SPEFPUOP_ARITH1(efdneg);
7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022
/* 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 */
7023 7024 7025 7026 7027 7028
GEN_SPEFPUOP_COMP(efdcmpgt);
GEN_SPEFPUOP_COMP(efdcmplt);
GEN_SPEFPUOP_COMP(efdcmpeq);
GEN_SPEFPUOP_COMP(efdtstgt);
GEN_SPEFPUOP_COMP(efdtstlt);
GEN_SPEFPUOP_COMP(efdtsteq);
7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047

/* 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 已提交
7048 7049 7050
/* End opcode list */
GEN_OPCODE_MARK(end);

7051
#include "translate_init.c"
7052
#include "helper_regs.h"
B
bellard 已提交
7053

7054
/*****************************************************************************/
7055
/* Misc PowerPC helpers */
7056 7057 7058
void cpu_dump_state (CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
B
bellard 已提交
7059
{
7060 7061 7062
#define RGPL  4
#define RFPL  4

B
bellard 已提交
7063 7064
    int i;

J
j_mayer 已提交
7065
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
A
aurel32 已提交
7066
                env->nip, env->lr, env->ctr, env->xer);
7067 7068
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
7069
#if !defined(NO_TIMER_DUMP)
J
j_mayer 已提交
7070
    cpu_fprintf(f, "TB %08x %08x "
7071 7072 7073 7074
#if !defined(CONFIG_USER_ONLY)
                "DECR %08x"
#endif
                "\n",
J
j_mayer 已提交
7075
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
7076 7077 7078 7079
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
7080
#endif
7081
    for (i = 0; i < 32; i++) {
7082 7083
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
7084
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
7085
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
7086
            cpu_fprintf(f, "\n");
7087
    }
7088
    cpu_fprintf(f, "CR ");
7089
    for (i = 0; i < 8; i++)
B
bellard 已提交
7090 7091
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
7092 7093 7094 7095 7096 7097 7098 7099
    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 已提交
7100
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
7101
    }
7102
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
7103 7104 7105
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
7106
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
7107
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
7108
            cpu_fprintf(f, "\n");
B
bellard 已提交
7109
    }
7110
#if !defined(CONFIG_USER_ONLY)
7111
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
7112
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
7113
#endif
B
bellard 已提交
7114

7115 7116
#undef RGPL
#undef RFPL
B
bellard 已提交
7117 7118
}

7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165
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
}

7166
/*****************************************************************************/
7167 7168 7169
static always_inline void gen_intermediate_code_internal (CPUState *env,
                                                          TranslationBlock *tb,
                                                          int search_pc)
B
bellard 已提交
7170
{
7171
    DisasContext ctx, *ctxp = &ctx;
B
bellard 已提交
7172
    opc_handler_t **table, *handler;
B
bellard 已提交
7173
    target_ulong pc_start;
B
bellard 已提交
7174
    uint16_t *gen_opc_end;
7175
    int supervisor, little_endian;
7176
    CPUBreakpoint *bp;
B
bellard 已提交
7177
    int j, lj = -1;
P
pbrook 已提交
7178 7179
    int num_insns;
    int max_insns;
B
bellard 已提交
7180 7181 7182

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7183 7184 7185
#if defined(OPTIMIZE_FPRF_UPDATE)
    gen_fprf_ptr = gen_fprf_buf;
#endif
B
bellard 已提交
7186
    ctx.nip = pc_start;
B
bellard 已提交
7187
    ctx.tb = tb;
7188
    ctx.exception = POWERPC_EXCP_NONE;
7189
    ctx.spr_cb = env->spr_cb;
7190 7191
    supervisor = env->mmu_idx;
#if !defined(CONFIG_USER_ONLY)
7192
    ctx.supervisor = supervisor;
7193
#endif
7194
    little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
7195 7196
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
7197
    ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
7198
#else
7199
    ctx.mem_idx = (supervisor << 1) | little_endian;
7200
#endif
7201
    ctx.dcache_line_size = env->dcache_line_size;
B
bellard 已提交
7202
    ctx.fpu_enabled = msr_fp;
7203
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
7204 7205 7206
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
7207 7208 7209 7210
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
7211
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
7212
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
7213
    else
7214
        ctx.singlestep_enabled = 0;
7215
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
7216 7217 7218
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
7219
#if defined (DO_SINGLE_STEP) && 0
7220 7221 7222
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
7223 7224 7225 7226 7227 7228
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
7229
    /* Set env in case of segfault during code fetch */
7230
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
7231 7232 7233
        if (unlikely(env->breakpoints)) {
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
                if (bp->pc == ctx.nip) {
7234
                    gen_update_nip(&ctx, ctx.nip);
7235 7236 7237 7238 7239
                    gen_op_debug();
                    break;
                }
            }
        }
7240
        if (unlikely(search_pc)) {
B
bellard 已提交
7241 7242 7243 7244 7245
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
7246
                gen_opc_pc[lj] = ctx.nip;
B
bellard 已提交
7247
                gen_opc_instr_start[lj] = 1;
P
pbrook 已提交
7248
                gen_opc_icount[lj] = num_insns;
B
bellard 已提交
7249 7250
            }
        }
7251 7252
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
B
bellard 已提交
7253
            fprintf(logfile, "----------------\n");
7254
            fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
7255
                    ctx.nip, supervisor, (int)msr_ir);
7256 7257
        }
#endif
P
pbrook 已提交
7258 7259
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
7260 7261 7262 7263
        if (unlikely(little_endian)) {
            ctx.opcode = bswap32(ldl_code(ctx.nip));
        } else {
            ctx.opcode = ldl_code(ctx.nip);
7264
        }
7265 7266
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
7267
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
7268
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
7269
                    opc3(ctx.opcode), little_endian ? "little" : "big");
B
bellard 已提交
7270 7271
        }
#endif
B
bellard 已提交
7272
        ctx.nip += 4;
7273
        table = env->opcodes;
P
pbrook 已提交
7274
        num_insns++;
B
bellard 已提交
7275 7276 7277 7278 7279 7280 7281 7282 7283 7284
        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 ? */
7285
        if (unlikely(handler->handler == &gen_invalid)) {
J
j_mayer 已提交
7286
            if (loglevel != 0) {
7287
                fprintf(logfile, "invalid/unsupported opcode: "
7288
                        "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
7289
                        opc1(ctx.opcode), opc2(ctx.opcode),
7290
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
7291 7292
            } else {
                printf("invalid/unsupported opcode: "
7293
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
B
bellard 已提交
7294
                       opc1(ctx.opcode), opc2(ctx.opcode),
7295
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
7296
            }
7297 7298
        } else {
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
J
j_mayer 已提交
7299
                if (loglevel != 0) {
B
bellard 已提交
7300
                    fprintf(logfile, "invalid bits: %08x for opcode: "
7301
                            "%02x - %02x - %02x (%08x) " ADDRX "\n",
B
bellard 已提交
7302 7303
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
                            opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
7304
                            ctx.opcode, ctx.nip - 4);
7305 7306
                } else {
                    printf("invalid bits: %08x for opcode: "
7307
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
7308 7309
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
                           opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
7310
                           ctx.opcode, ctx.nip - 4);
7311
                }
7312
                GEN_EXCP_INVAL(ctxp);
B
bellard 已提交
7313
                break;
B
bellard 已提交
7314 7315
            }
        }
B
bellard 已提交
7316
        (*(handler->handler))(&ctx);
7317 7318 7319
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
7320
        /* Check trace mode exceptions */
7321 7322 7323 7324 7325
        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)) {
7326
            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
7327
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
7328 7329
                            (env->singlestep_enabled) ||
                            num_insns >= max_insns)) {
7330 7331 7332
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
7333
            break;
7334
        }
7335 7336 7337 7338
#if defined (DO_SINGLE_STEP)
        break;
#endif
    }
P
pbrook 已提交
7339 7340
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
7341
    if (ctx.exception == POWERPC_EXCP_NONE) {
7342
        gen_goto_tb(&ctx, 0, ctx.nip);
7343
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
7344 7345 7346 7347
        if (unlikely(env->singlestep_enabled)) {
            gen_update_nip(&ctx, ctx.nip);
            gen_op_debug();
        }
7348
        /* Generate the return instruction */
B
bellard 已提交
7349
        tcg_gen_exit_tb(0);
7350
    }
P
pbrook 已提交
7351
    gen_icount_end(tb, num_insns);
B
bellard 已提交
7352
    *gen_opc_ptr = INDEX_op_end;
7353
    if (unlikely(search_pc)) {
7354 7355 7356 7357 7358
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
B
bellard 已提交
7359
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
7360
        tb->icount = num_insns;
7361
    }
7362
#if defined(DEBUG_DISAS)
7363
    if (loglevel & CPU_LOG_TB_CPU) {
7364
        fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
B
bellard 已提交
7365
        cpu_dump_state(env, logfile, fprintf, 0);
7366 7367
    }
    if (loglevel & CPU_LOG_TB_IN_ASM) {
7368
        int flags;
7369
        flags = env->bfd_mach;
7370
        flags |= little_endian << 16;
B
bellard 已提交
7371
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
7372
        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
B
bellard 已提交
7373
        fprintf(logfile, "\n");
7374
    }
B
bellard 已提交
7375 7376 7377
#endif
}

7378
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
7379
{
7380
    gen_intermediate_code_internal(env, tb, 0);
B
bellard 已提交
7381 7382
}

7383
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
7384
{
7385
    gen_intermediate_code_internal(env, tb, 1);
B
bellard 已提交
7386
}
A
aurel32 已提交
7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428

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