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

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

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

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

P
pbrook 已提交
46 47 48 49 50 51 52 53 54 55 56 57 58
static TCGv cpu_env;

#include "gen-icount.h"

void ppc_translate_init(void)
{
    int done_init = 0;
    if (done_init)
        return;
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
    done_init = 1;
}

59 60 61 62
#if defined(OPTIMIZE_FPRF_UPDATE)
static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
static uint16_t **gen_fprf_ptr;
#endif
B
bellard 已提交
63

64
static always_inline void gen_set_T0 (target_ulong val)
65 66 67 68 69 70 71 72 73
{
#if defined(TARGET_PPC64)
    if (val >> 32)
        gen_op_set_T0_64(val >> 32, val);
    else
#endif
        gen_op_set_T0(val);
}

74
static always_inline void gen_set_T1 (target_ulong val)
75 76 77 78 79 80 81 82 83 84
{
#if defined(TARGET_PPC64)
    if (val >> 32)
        gen_op_set_T1_64(val >> 32, val);
    else
#endif
        gen_op_set_T1(val);
}

#define GEN8(func, NAME)                                                      \
85 86 87 88
static GenOpFunc *NAME ## _table [8] = {                                      \
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
};                                                                            \
89
static always_inline void func (int n)                                        \
90 91 92 93 94 95 96 97 98 99 100
{                                                                             \
    NAME ## _table[n]();                                                      \
}

#define GEN16(func, NAME)                                                     \
static GenOpFunc *NAME ## _table [16] = {                                     \
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
};                                                                            \
101
static always_inline void func (int n)                                        \
102 103
{                                                                             \
    NAME ## _table[n]();                                                      \
104 105
}

106
#define GEN32(func, NAME)                                                     \
107 108 109 110 111 112 113 114 115 116
static GenOpFunc *NAME ## _table [32] = {                                     \
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
};                                                                            \
117
static always_inline void func (int n)                                        \
118 119 120 121 122 123 124 125
{                                                                             \
    NAME ## _table[n]();                                                      \
}

/* Condition register moves */
GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
126
#if 0 // Unused
127
GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
128
#endif
129

130 131 132 133 134 135 136
/* General purpose registers moves */
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);

GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
137
#if 0 // unused
138
GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
139
#endif
140

B
bellard 已提交
141 142 143 144 145 146
/* floating point registers moves */
GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr);
GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr);
GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr);
GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr);
147
#if 0 // unused
B
bellard 已提交
148
GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr);
149
#endif
B
bellard 已提交
150 151 152 153

/* internal defines */
typedef struct DisasContext {
    struct TranslationBlock *tb;
B
bellard 已提交
154
    target_ulong nip;
B
bellard 已提交
155
    uint32_t opcode;
156
    uint32_t exception;
B
bellard 已提交
157 158 159
    /* Routine used to access memory */
    int mem_idx;
    /* Translation flags */
160
#if !defined(CONFIG_USER_ONLY)
B
bellard 已提交
161
    int supervisor;
162 163 164
#endif
#if defined(TARGET_PPC64)
    int sf_mode;
165
#endif
B
bellard 已提交
166
    int fpu_enabled;
167
    int altivec_enabled;
168
    int spe_enabled;
169
    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
170
    int singlestep_enabled;
171
    int dcache_line_size;
B
bellard 已提交
172 173
} DisasContext;

174
struct opc_handler_t {
B
bellard 已提交
175 176
    /* invalid bits */
    uint32_t inval;
177
    /* instruction type */
178
    uint64_t type;
B
bellard 已提交
179 180
    /* handler */
    void (*handler)(DisasContext *ctx);
181
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
182
    const unsigned char *oname;
183 184
#endif
#if defined(DO_PPC_STATISTICS)
185 186
    uint64_t count;
#endif
187
};
B
bellard 已提交
188

189
static always_inline void gen_set_Rc0 (DisasContext *ctx)
190
{
191 192 193 194 195 196
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_cmpi_64(0);
    else
#endif
        gen_op_cmpi(0);
197 198 199
    gen_op_set_Rc0();
}

200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
static always_inline void gen_reset_fpstatus (void)
{
#ifdef CONFIG_SOFTFLOAT
    gen_op_reset_fpstatus();
#endif
}

static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
{
    if (set_fprf != 0) {
        /* This case might be optimized later */
#if defined(OPTIMIZE_FPRF_UPDATE)
        *gen_fprf_ptr++ = gen_opc_ptr;
#endif
        gen_op_compute_fprf(1);
        if (unlikely(set_rc))
            gen_op_store_T0_crf(1);
        gen_op_float_check_status();
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
        gen_op_compute_fprf(0);
        gen_op_store_T0_crf(1);
        if (set_fprf)
            gen_op_float_check_status();
    }
}

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

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

238
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
239 240 241 242 243 244 245 246 247
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_update_nip_64(nip >> 32, nip);
    else
#endif
        gen_op_update_nip(nip);
}

248
#define GEN_EXCP(ctx, excp, error)                                            \
B
bellard 已提交
249
do {                                                                          \
250
    if ((ctx)->exception == POWERPC_EXCP_NONE) {                              \
251
        gen_update_nip(ctx, (ctx)->nip);                                      \
252 253 254
    }                                                                         \
    gen_op_raise_exception_err((excp), (error));                              \
    ctx->exception = (excp);                                                  \
B
bellard 已提交
255 256
} while (0)

257 258 259
#define GEN_EXCP_INVAL(ctx)                                                   \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
260

261 262 263
#define GEN_EXCP_PRIVOPC(ctx)                                                 \
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
264

265 266 267 268 269 270 271 272 273
#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)
274

275 276 277
#define GEN_EXCP_NO_VR(ctx)                                                   \
GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)

278
/* Stop translation */
279
static always_inline void GEN_STOP (DisasContext *ctx)
280
{
281
    gen_update_nip(ctx, ctx->nip);
282
    ctx->exception = POWERPC_EXCP_STOP;
283 284
}

285
/* No need to update nip here, as execution flow will change */
286
static always_inline void GEN_SYNC (DisasContext *ctx)
287
{
288
    ctx->exception = POWERPC_EXCP_SYNC;
289 290
}

B
bellard 已提交
291 292 293 294 295
#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)

296 297 298 299 300
#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 已提交
301 302
typedef struct opcode_t {
    unsigned char opc1, opc2, opc3;
T
ths 已提交
303
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
304 305 306 307
    unsigned char pad[5];
#else
    unsigned char pad[1];
#endif
B
bellard 已提交
308
    opc_handler_t handler;
309
    const unsigned char *oname;
B
bellard 已提交
310 311
} opcode_t;

312
/*****************************************************************************/
B
bellard 已提交
313 314
/***                           Instruction decoding                        ***/
#define EXTRACT_HELPER(name, shift, nb)                                       \
315
static always_inline uint32_t name (uint32_t opcode)                          \
B
bellard 已提交
316 317 318 319 320
{                                                                             \
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
}

#define EXTRACT_SHELPER(name, shift, nb)                                      \
321
static always_inline int32_t name (uint32_t opcode)                           \
B
bellard 已提交
322
{                                                                             \
323
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
B
bellard 已提交
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
}

/* 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 */
351
EXTRACT_HELPER(_SPR, 11, 10);
352
static always_inline uint32_t SPR (uint32_t opcode)
353 354 355 356 357
{
    uint32_t sprn = _SPR(opcode);

    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
}
B
bellard 已提交
358 359 360 361 362 363 364 365 366 367 368 369 370 371
/***                              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 已提交
372 373
/* Trap operand */
EXTRACT_HELPER(TO, 21, 5);
B
bellard 已提交
374 375 376 377

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

B
bellard 已提交
380 381 382 383
/***                            Jump target decoding                       ***/
/* Displacement */
EXTRACT_SHELPER(d, 0, 16);
/* Immediate address */
384
static always_inline target_ulong LI (uint32_t opcode)
B
bellard 已提交
385 386 387 388
{
    return (opcode >> 0) & 0x03FFFFFC;
}

389
static always_inline uint32_t BD (uint32_t opcode)
B
bellard 已提交
390 391 392 393 394 395 396 397 398 399 400 401
{
    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 */
402
static always_inline target_ulong MASK (uint32_t start, uint32_t end)
B
bellard 已提交
403
{
404
    target_ulong ret;
B
bellard 已提交
405

406 407
#if defined(TARGET_PPC64)
    if (likely(start == 0)) {
408
        ret = UINT64_MAX << (63 - end);
409
    } else if (likely(end == 63)) {
410
        ret = UINT64_MAX >> start;
411 412 413
    }
#else
    if (likely(start == 0)) {
414
        ret = UINT32_MAX << (31  - end);
415
    } else if (likely(end == 31)) {
416
        ret = UINT32_MAX >> start;
417 418 419 420 421 422 423 424
    }
#endif
    else {
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
            (((target_ulong)(-1ULL) >> (end)) >> 1);
        if (unlikely(start > end))
            return ~ret;
    }
B
bellard 已提交
425 426 427 428

    return ret;
}

429 430 431
/*****************************************************************************/
/* PowerPC Instructions types definitions                                    */
enum {
432
    PPC_NONE           = 0x0000000000000000ULL,
433
    /* PowerPC base instructions set                                         */
434 435
    PPC_INSNS_BASE     = 0x0000000000000001ULL,
    /*   integer operations instructions                                     */
436
#define PPC_INTEGER PPC_INSNS_BASE
437
    /*   flow control instructions                                           */
438
#define PPC_FLOW    PPC_INSNS_BASE
439
    /*   virtual memory instructions                                         */
440
#define PPC_MEM     PPC_INSNS_BASE
441
    /*   ld/st with reservation instructions                                 */
442
#define PPC_RES     PPC_INSNS_BASE
443
    /*   spr/msr access instructions                                         */
444
#define PPC_MISC    PPC_INSNS_BASE
445 446
    /* Deprecated instruction sets                                           */
    /*   Original POWER instruction set                                      */
447
    PPC_POWER          = 0x0000000000000002ULL,
448
    /*   POWER2 instruction set extension                                    */
449
    PPC_POWER2         = 0x0000000000000004ULL,
450
    /*   Power RTC support                                                   */
451
    PPC_POWER_RTC      = 0x0000000000000008ULL,
452
    /*   Power-to-PowerPC bridge (601)                                       */
453
    PPC_POWER_BR       = 0x0000000000000010ULL,
454
    /* 64 bits PowerPC instruction set                                       */
455
    PPC_64B            = 0x0000000000000020ULL,
456
    /*   New 64 bits extensions (PowerPC 2.0x)                               */
457
    PPC_64BX           = 0x0000000000000040ULL,
458
    /*   64 bits hypervisor extensions                                       */
459
    PPC_64H            = 0x0000000000000080ULL,
460
    /*   New wait instruction (PowerPC 2.0x)                                 */
461
    PPC_WAIT           = 0x0000000000000100ULL,
462
    /*   Time base mftb instruction                                          */
463
    PPC_MFTB           = 0x0000000000000200ULL,
464 465 466

    /* Fixed-point unit extensions                                           */
    /*   PowerPC 602 specific                                                */
467
    PPC_602_SPEC       = 0x0000000000000400ULL,
468 469 470 471 472 473
    /*   isel instruction                                                    */
    PPC_ISEL           = 0x0000000000000800ULL,
    /*   popcntb instruction                                                 */
    PPC_POPCNTB        = 0x0000000000001000ULL,
    /*   string load / store                                                 */
    PPC_STRING         = 0x0000000000002000ULL,
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490

    /* 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                                          */
491
    PPC_SPE            = 0x0000000002000000ULL,
492
    /*   PowerPC 2.03 SPE floating-point extension                           */
493
    PPC_SPEFPU         = 0x0000000004000000ULL,
494

495
    /* Optional memory control instructions                                  */
496 497 498 499 500 501 502 503 504
    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                                            */
505
    PPC_CACHE          = 0x0000000200000000ULL,
506
    /*   icbi instruction                                                    */
507
    PPC_CACHE_ICBI     = 0x0000000400000000ULL,
508
    /*   dcbz instruction with fixed cache line size                         */
509
    PPC_CACHE_DCBZ     = 0x0000000800000000ULL,
510
    /*   dcbz instruction with tunable cache line size                       */
511
    PPC_CACHE_DCBZT    = 0x0000001000000000ULL,
512
    /*   dcba instruction                                                    */
513 514 515
    PPC_CACHE_DCBA     = 0x0000002000000000ULL,
    /*   Freescale cache locking instructions                                */
    PPC_CACHE_LOCK     = 0x0000004000000000ULL,
516 517 518

    /* MMU related extensions                                                */
    /*   external control instructions                                       */
519
    PPC_EXTERN         = 0x0000010000000000ULL,
520
    /*   segment register access instructions                                */
521
    PPC_SEGMENT        = 0x0000020000000000ULL,
522
    /*   PowerPC 6xx TLB management instructions                             */
523
    PPC_6xx_TLB        = 0x0000040000000000ULL,
524
    /* PowerPC 74xx TLB management instructions                              */
525
    PPC_74xx_TLB       = 0x0000080000000000ULL,
526
    /*   PowerPC 40x TLB management instructions                             */
527
    PPC_40x_TLB        = 0x0000100000000000ULL,
528
    /*   segment register access instructions for PowerPC 64 "bridge"        */
529
    PPC_SEGMENT_64B    = 0x0000200000000000ULL,
530
    /*   SLB management                                                      */
531
    PPC_SLBI           = 0x0000400000000000ULL,
532

533
    /* Embedded PowerPC dedicated instructions                               */
534
    PPC_WRTEE          = 0x0001000000000000ULL,
535
    /* PowerPC 40x exception model                                           */
536
    PPC_40x_EXCP       = 0x0002000000000000ULL,
537
    /* PowerPC 405 Mac instructions                                          */
538
    PPC_405_MAC        = 0x0004000000000000ULL,
539
    /* PowerPC 440 specific instructions                                     */
540
    PPC_440_SPEC       = 0x0008000000000000ULL,
541
    /* BookE (embedded) PowerPC specification                                */
542 543 544 545 546 547 548
    PPC_BOOKE          = 0x0010000000000000ULL,
    /* mfapidi instruction                                                   */
    PPC_MFAPIDI        = 0x0020000000000000ULL,
    /* tlbiva instruction                                                    */
    PPC_TLBIVA         = 0x0040000000000000ULL,
    /* tlbivax instruction                                                   */
    PPC_TLBIVAX        = 0x0080000000000000ULL,
549
    /* PowerPC 4xx dedicated instructions                                    */
550
    PPC_4xx_COMMON     = 0x0100000000000000ULL,
551
    /* PowerPC 40x ibct instructions                                         */
552
    PPC_40x_ICBT       = 0x0200000000000000ULL,
553
    /* rfmci is not implemented in all BookE PowerPC                         */
554 555 556 557 558 559 560
    PPC_RFMCI          = 0x0400000000000000ULL,
    /* rfdi instruction                                                      */
    PPC_RFDI           = 0x0800000000000000ULL,
    /* DCR accesses                                                          */
    PPC_DCR            = 0x1000000000000000ULL,
    /* DCR extended accesse                                                  */
    PPC_DCRX           = 0x2000000000000000ULL,
561
    /* user-mode DCR access, implemented in PowerPC 460                      */
562
    PPC_DCRUX          = 0x4000000000000000ULL,
563 564 565 566
};

/*****************************************************************************/
/* PowerPC instructions table                                                */
567 568 569 570 571
#if HOST_LONG_BITS == 64
#define OPC_ALIGN 8
#else
#define OPC_ALIGN 4
#endif
B
bellard 已提交
572
#if defined(__APPLE__)
573
#define OPCODES_SECTION                                                       \
574
    __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
575
#else
576
#define OPCODES_SECTION                                                       \
577
    __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
B
bellard 已提交
578 579
#endif

580
#if defined(DO_PPC_STATISTICS)
B
bellard 已提交
581
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
582
OPCODES_SECTION opcode_t opc_##name = {                                       \
B
bellard 已提交
583 584 585
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
586
    .pad  = { 0, },                                                           \
B
bellard 已提交
587 588
    .handler = {                                                              \
        .inval   = invl,                                                      \
589
        .type = _typ,                                                         \
B
bellard 已提交
590
        .handler = &gen_##name,                                               \
591
        .oname = stringify(name),                                             \
B
bellard 已提交
592
    },                                                                        \
593
    .oname = stringify(name),                                                 \
B
bellard 已提交
594
}
595 596 597 598 599 600 601 602 603 604 605 606 607 608
#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,                                                            \
}
609 610 611 612 613 614 615 616 617 618 619 620 621 622
#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),                                                 \
}
623 624 625 626 627 628 629 630 631 632 633 634 635
#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,                                                            \
}
636
#endif
B
bellard 已提交
637 638

#define GEN_OPCODE_MARK(name)                                                 \
639
OPCODES_SECTION opcode_t opc_##name = {                                       \
B
bellard 已提交
640 641 642
    .opc1 = 0xFF,                                                             \
    .opc2 = 0xFF,                                                             \
    .opc3 = 0xFF,                                                             \
643
    .pad  = { 0, },                                                           \
B
bellard 已提交
644 645
    .handler = {                                                              \
        .inval   = 0x00000000,                                                \
646
        .type = 0x00,                                                         \
B
bellard 已提交
647 648
        .handler = NULL,                                                      \
    },                                                                        \
649
    .oname = stringify(name),                                                 \
B
bellard 已提交
650 651 652 653 654 655
}

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

/* Invalid instruction */
656 657
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
{
658
    GEN_EXCP_INVAL(ctx);
659 660
}

B
bellard 已提交
661 662
static opc_handler_t invalid_handler = {
    .inval   = 0xFFFFFFFF,
663
    .type    = PPC_NONE,
B
bellard 已提交
664 665 666 667
    .handler = gen_invalid,
};

/***                           Integer arithmetic                          ***/
668 669
#define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval, type)                 \
GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
B
bellard 已提交
670 671 672 673 674
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
675 676
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
677 678
}

679 680
#define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval, type)               \
GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
B
bellard 已提交
681 682 683 684 685
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
686 687
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
688 689
}

690 691
#define __GEN_INT_ARITH1(name, opc1, opc2, opc3, type)                        \
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
B
bellard 已提交
692 693 694 695
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
696 697
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
698
}
699 700
#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3, type)                      \
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
B
bellard 已提交
701 702 703 704
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
705 706
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
707 708 709
}

/* Two operands arithmetic functions */
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
#define GEN_INT_ARITH2(name, opc1, opc2, opc3, type)                          \
__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000, type)                    \
__GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)

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

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

#if defined(TARGET_PPC64)
#define __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, inval, type)              \
GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
    if (ctx->sf_mode)                                                         \
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
}

#define __GEN_INT_ARITH2_O_64(name, opc1, opc2, opc3, inval, type)            \
GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
    if (ctx->sf_mode)                                                         \
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
}

#define __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type)                     \
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    if (ctx->sf_mode)                                                         \
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
}
#define __GEN_INT_ARITH1_O_64(name, opc1, opc2, opc3, type)                   \
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    if (ctx->sf_mode)                                                         \
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
}

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

/* Two operands arithmetic functions with no overflow allowed */
783 784
#define GEN_INT_ARITHN_64(name, opc1, opc2, opc3, type)                       \
__GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000400, type)
B
bellard 已提交
785 786

/* One operand arithmetic functions */
787 788 789 790 791 792 793 794
#define GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type)                       \
__GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type)                             \
__GEN_INT_ARITH1_O_64(name##o, opc1, opc2, opc3 | 0x10, type)
#else
#define GEN_INT_ARITH2_64 GEN_INT_ARITH2
#define GEN_INT_ARITHN_64 GEN_INT_ARITHN
#define GEN_INT_ARITH1_64 GEN_INT_ARITH1
#endif
B
bellard 已提交
795 796

/* add    add.    addo    addo.    */
797
static always_inline void gen_op_addo (void)
798 799 800 801 802 803 804
{
    gen_op_move_T2_T0();
    gen_op_add();
    gen_op_check_addo();
}
#if defined(TARGET_PPC64)
#define gen_op_add_64 gen_op_add
805
static always_inline void gen_op_addo_64 (void)
806 807 808 809 810 811 812
{
    gen_op_move_T2_T0();
    gen_op_add();
    gen_op_check_addo_64();
}
#endif
GEN_INT_ARITH2_64 (add,    0x1F, 0x0A, 0x08, PPC_INTEGER);
B
bellard 已提交
813
/* addc   addc.   addco   addco.   */
814
static always_inline void gen_op_addc (void)
815 816 817 818 819
{
    gen_op_move_T2_T0();
    gen_op_add();
    gen_op_check_addc();
}
820
static always_inline void gen_op_addco (void)
821 822 823 824 825 826 827
{
    gen_op_move_T2_T0();
    gen_op_add();
    gen_op_check_addc();
    gen_op_check_addo();
}
#if defined(TARGET_PPC64)
828
static always_inline void gen_op_addc_64 (void)
829 830 831 832 833
{
    gen_op_move_T2_T0();
    gen_op_add();
    gen_op_check_addc_64();
}
834
static always_inline void gen_op_addco_64 (void)
835 836 837 838 839 840 841 842
{
    gen_op_move_T2_T0();
    gen_op_add();
    gen_op_check_addc_64();
    gen_op_check_addo_64();
}
#endif
GEN_INT_ARITH2_64 (addc,   0x1F, 0x0A, 0x00, PPC_INTEGER);
B
bellard 已提交
843
/* adde   adde.   addeo   addeo.   */
844
static always_inline void gen_op_addeo (void)
845 846 847 848 849 850
{
    gen_op_move_T2_T0();
    gen_op_adde();
    gen_op_check_addo();
}
#if defined(TARGET_PPC64)
851
static always_inline void gen_op_addeo_64 (void)
852 853 854 855 856 857 858
{
    gen_op_move_T2_T0();
    gen_op_adde_64();
    gen_op_check_addo_64();
}
#endif
GEN_INT_ARITH2_64 (adde,   0x1F, 0x0A, 0x04, PPC_INTEGER);
B
bellard 已提交
859
/* addme  addme.  addmeo  addmeo.  */
860
static always_inline void gen_op_addme (void)
861 862 863 864 865
{
    gen_op_move_T1_T0();
    gen_op_add_me();
}
#if defined(TARGET_PPC64)
866
static always_inline void gen_op_addme_64 (void)
867 868 869 870 871 872
{
    gen_op_move_T1_T0();
    gen_op_add_me_64();
}
#endif
GEN_INT_ARITH1_64 (addme,  0x1F, 0x0A, 0x07, PPC_INTEGER);
B
bellard 已提交
873
/* addze  addze.  addzeo  addzeo.  */
874
static always_inline void gen_op_addze (void)
875 876 877 878 879
{
    gen_op_move_T2_T0();
    gen_op_add_ze();
    gen_op_check_addc();
}
880
static always_inline void gen_op_addzeo (void)
881 882 883 884 885 886 887
{
    gen_op_move_T2_T0();
    gen_op_add_ze();
    gen_op_check_addc();
    gen_op_check_addo();
}
#if defined(TARGET_PPC64)
888
static always_inline void gen_op_addze_64 (void)
889 890 891 892 893
{
    gen_op_move_T2_T0();
    gen_op_add_ze();
    gen_op_check_addc_64();
}
894
static always_inline void gen_op_addzeo_64 (void)
895 896 897 898 899 900 901 902
{
    gen_op_move_T2_T0();
    gen_op_add_ze();
    gen_op_check_addc_64();
    gen_op_check_addo_64();
}
#endif
GEN_INT_ARITH1_64 (addze,  0x1F, 0x0A, 0x06, PPC_INTEGER);
B
bellard 已提交
903
/* divw   divw.   divwo   divwo.   */
904
GEN_INT_ARITH2 (divw,   0x1F, 0x0B, 0x0F, PPC_INTEGER);
B
bellard 已提交
905
/* divwu  divwu.  divwuo  divwuo.  */
906
GEN_INT_ARITH2 (divwu,  0x1F, 0x0B, 0x0E, PPC_INTEGER);
B
bellard 已提交
907
/* mulhw  mulhw.                   */
908
GEN_INT_ARITHN (mulhw,  0x1F, 0x0B, 0x02, PPC_INTEGER);
B
bellard 已提交
909
/* mulhwu mulhwu.                  */
910
GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00, PPC_INTEGER);
B
bellard 已提交
911
/* mullw  mullw.  mullwo  mullwo.  */
912
GEN_INT_ARITH2 (mullw,  0x1F, 0x0B, 0x07, PPC_INTEGER);
B
bellard 已提交
913
/* neg    neg.    nego    nego.    */
914
GEN_INT_ARITH1_64 (neg,    0x1F, 0x08, 0x03, PPC_INTEGER);
B
bellard 已提交
915
/* subf   subf.   subfo   subfo.   */
916
static always_inline void gen_op_subfo (void)
917
{
918
    gen_op_moven_T2_T0();
919
    gen_op_subf();
920
    gen_op_check_addo();
921 922 923
}
#if defined(TARGET_PPC64)
#define gen_op_subf_64 gen_op_subf
924
static always_inline void gen_op_subfo_64 (void)
925
{
926
    gen_op_moven_T2_T0();
927
    gen_op_subf();
928
    gen_op_check_addo_64();
929 930 931
}
#endif
GEN_INT_ARITH2_64 (subf,   0x1F, 0x08, 0x01, PPC_INTEGER);
B
bellard 已提交
932
/* subfc  subfc.  subfco  subfco.  */
933
static always_inline void gen_op_subfc (void)
934 935 936 937
{
    gen_op_subf();
    gen_op_check_subfc();
}
938
static always_inline void gen_op_subfco (void)
939
{
940
    gen_op_moven_T2_T0();
941 942
    gen_op_subf();
    gen_op_check_subfc();
943
    gen_op_check_addo();
944 945
}
#if defined(TARGET_PPC64)
946
static always_inline void gen_op_subfc_64 (void)
947 948 949 950
{
    gen_op_subf();
    gen_op_check_subfc_64();
}
951
static always_inline void gen_op_subfco_64 (void)
952
{
953
    gen_op_moven_T2_T0();
954 955
    gen_op_subf();
    gen_op_check_subfc_64();
956
    gen_op_check_addo_64();
957 958 959
}
#endif
GEN_INT_ARITH2_64 (subfc,  0x1F, 0x08, 0x00, PPC_INTEGER);
B
bellard 已提交
960
/* subfe  subfe.  subfeo  subfeo.  */
961
static always_inline void gen_op_subfeo (void)
962
{
963
    gen_op_moven_T2_T0();
964
    gen_op_subfe();
965
    gen_op_check_addo();
966 967 968
}
#if defined(TARGET_PPC64)
#define gen_op_subfe_64 gen_op_subfe
969
static always_inline void gen_op_subfeo_64 (void)
970
{
971
    gen_op_moven_T2_T0();
972
    gen_op_subfe_64();
973
    gen_op_check_addo_64();
974 975 976
}
#endif
GEN_INT_ARITH2_64 (subfe,  0x1F, 0x08, 0x04, PPC_INTEGER);
B
bellard 已提交
977
/* subfme subfme. subfmeo subfmeo. */
978
GEN_INT_ARITH1_64 (subfme, 0x1F, 0x08, 0x07, PPC_INTEGER);
B
bellard 已提交
979
/* subfze subfze. subfzeo subfzeo. */
980
GEN_INT_ARITH1_64 (subfze, 0x1F, 0x08, 0x06, PPC_INTEGER);
B
bellard 已提交
981 982 983
/* addi */
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
984
    target_long simm = SIMM(ctx->opcode);
B
bellard 已提交
985 986

    if (rA(ctx->opcode) == 0) {
987
        /* li case */
988
        gen_set_T0(simm);
B
bellard 已提交
989 990
    } else {
        gen_op_load_gpr_T0(rA(ctx->opcode));
991 992
        if (likely(simm != 0))
            gen_op_addi(simm);
B
bellard 已提交
993 994 995 996 997 998
    }
    gen_op_store_T0_gpr(rD(ctx->opcode));
}
/* addic */
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
999 1000
    target_long simm = SIMM(ctx->opcode);

B
bellard 已提交
1001
    gen_op_load_gpr_T0(rA(ctx->opcode));
1002 1003 1004 1005 1006 1007 1008 1009 1010
    if (likely(simm != 0)) {
        gen_op_move_T2_T0();
        gen_op_addi(simm);
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_check_addc_64();
        else
#endif
            gen_op_check_addc();
J
j_mayer 已提交
1011 1012
    } else {
        gen_op_clear_xer_ca();
1013
    }
B
bellard 已提交
1014 1015 1016
    gen_op_store_T0_gpr(rD(ctx->opcode));
}
/* addic. */
1017
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1018
{
1019 1020
    target_long simm = SIMM(ctx->opcode);

B
bellard 已提交
1021
    gen_op_load_gpr_T0(rA(ctx->opcode));
1022 1023 1024 1025 1026 1027 1028 1029 1030
    if (likely(simm != 0)) {
        gen_op_move_T2_T0();
        gen_op_addi(simm);
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_check_addc_64();
        else
#endif
            gen_op_check_addc();
J
j_mayer 已提交
1031 1032
    } else {
        gen_op_clear_xer_ca();
1033
    }
B
bellard 已提交
1034
    gen_op_store_T0_gpr(rD(ctx->opcode));
1035
    gen_set_Rc0(ctx);
B
bellard 已提交
1036 1037 1038 1039
}
/* addis */
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1040
    target_long simm = SIMM(ctx->opcode);
B
bellard 已提交
1041 1042

    if (rA(ctx->opcode) == 0) {
1043
        /* lis case */
1044
        gen_set_T0(simm << 16);
B
bellard 已提交
1045 1046
    } else {
        gen_op_load_gpr_T0(rA(ctx->opcode));
1047 1048
        if (likely(simm != 0))
            gen_op_addi(simm << 16);
B
bellard 已提交
1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
    }
    gen_op_store_T0_gpr(rD(ctx->opcode));
}
/* mulli */
GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_mulli(SIMM(ctx->opcode));
    gen_op_store_T0_gpr(rD(ctx->opcode));
}
/* subfic */
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
1063 1064 1065 1066 1067 1068
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_subfic_64(SIMM(ctx->opcode));
    else
#endif
        gen_op_subfic(SIMM(ctx->opcode));
B
bellard 已提交
1069 1070 1071
    gen_op_store_T0_gpr(rD(ctx->opcode));
}

1072 1073
#if defined(TARGET_PPC64)
/* mulhd  mulhd.                   */
1074
GEN_INT_ARITHN (mulhd,  0x1F, 0x09, 0x02, PPC_64B);
1075
/* mulhdu mulhdu.                  */
1076
GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_64B);
1077
/* mulld  mulld.  mulldo  mulldo.  */
1078
GEN_INT_ARITH2 (mulld,  0x1F, 0x09, 0x07, PPC_64B);
1079
/* divd   divd.   divdo   divdo.   */
1080
GEN_INT_ARITH2 (divd,   0x1F, 0x09, 0x0F, PPC_64B);
1081
/* divdu  divdu.  divduo  divduo.  */
1082
GEN_INT_ARITH2 (divdu,  0x1F, 0x09, 0x0E, PPC_64B);
1083 1084
#endif

B
bellard 已提交
1085
/***                           Integer comparison                          ***/
1086 1087 1088 1089 1090 1091
#if defined(TARGET_PPC64)
#define GEN_CMP(name, opc, type)                                              \
GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type)                          \
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1092
    if (ctx->sf_mode && (ctx->opcode & 0x00200000))                           \
1093 1094 1095 1096 1097 1098 1099 1100
        gen_op_##name##_64();                                                 \
    else                                                                      \
        gen_op_##name();                                                      \
    gen_op_store_T0_crf(crfD(ctx->opcode));                                   \
}
#else
#define GEN_CMP(name, opc, type)                                              \
GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type)                          \
B
bellard 已提交
1101 1102 1103 1104 1105 1106
{                                                                             \
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
    gen_op_##name();                                                          \
    gen_op_store_T0_crf(crfD(ctx->opcode));                                   \
}
1107
#endif
B
bellard 已提交
1108 1109

/* cmp */
1110
GEN_CMP(cmp, 0x00, PPC_INTEGER);
B
bellard 已提交
1111 1112 1113 1114
/* cmpi */
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
1115
#if defined(TARGET_PPC64)
1116
    if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1117 1118 1119 1120
        gen_op_cmpi_64(SIMM(ctx->opcode));
    else
#endif
        gen_op_cmpi(SIMM(ctx->opcode));
B
bellard 已提交
1121 1122 1123
    gen_op_store_T0_crf(crfD(ctx->opcode));
}
/* cmpl */
1124
GEN_CMP(cmpl, 0x01, PPC_INTEGER);
B
bellard 已提交
1125 1126 1127 1128
/* cmpli */
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
1129
#if defined(TARGET_PPC64)
1130
    if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1131 1132 1133 1134
        gen_op_cmpli_64(UIMM(ctx->opcode));
    else
#endif
        gen_op_cmpli(UIMM(ctx->opcode));
B
bellard 已提交
1135 1136 1137
    gen_op_store_T0_crf(crfD(ctx->opcode));
}

1138
/* isel (PowerPC 2.03 specification) */
A
aurel32 已提交
1139
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
{
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;

    if (rA(ctx->opcode) == 0) {
        gen_set_T0(0);
    } else {
        gen_op_load_gpr_T1(rA(ctx->opcode));
    }
    gen_op_load_gpr_T2(rB(ctx->opcode));
    mask = 1 << (3 - (bi & 0x03));
    gen_op_load_crf_T0(bi >> 2);
    gen_op_test_true(mask);
    gen_op_isel();
    gen_op_store_T0_gpr(rD(ctx->opcode));
}

B
bellard 已提交
1157
/***                            Integer logical                            ***/
1158 1159
#define __GEN_LOGICAL2(name, opc2, opc3, type)                                \
GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type)                         \
B
bellard 已提交
1160 1161 1162 1163 1164
{                                                                             \
    gen_op_load_gpr_T0(rS(ctx->opcode));                                      \
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1165 1166
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
1167
}
1168 1169
#define GEN_LOGICAL2(name, opc, type)                                         \
__GEN_LOGICAL2(name, 0x1C, opc, type)
B
bellard 已提交
1170

1171 1172
#define GEN_LOGICAL1(name, opc, type)                                         \
GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)                          \
B
bellard 已提交
1173 1174 1175 1176
{                                                                             \
    gen_op_load_gpr_T0(rS(ctx->opcode));                                      \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1177 1178
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
        gen_set_Rc0(ctx);                                                     \
B
bellard 已提交
1179 1180 1181
}

/* and & and. */
1182
GEN_LOGICAL2(and, 0x00, PPC_INTEGER);
B
bellard 已提交
1183
/* andc & andc. */
1184
GEN_LOGICAL2(andc, 0x01, PPC_INTEGER);
B
bellard 已提交
1185
/* andi. */
1186
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1187 1188
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
1189
    gen_op_andi_T0(UIMM(ctx->opcode));
B
bellard 已提交
1190
    gen_op_store_T0_gpr(rA(ctx->opcode));
1191
    gen_set_Rc0(ctx);
B
bellard 已提交
1192 1193
}
/* andis. */
1194
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
B
bellard 已提交
1195 1196
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
1197
    gen_op_andi_T0(UIMM(ctx->opcode) << 16);
B
bellard 已提交
1198
    gen_op_store_T0_gpr(rA(ctx->opcode));
1199
    gen_set_Rc0(ctx);
B
bellard 已提交
1200 1201 1202
}

/* cntlzw */
1203
GEN_LOGICAL1(cntlzw, 0x00, PPC_INTEGER);
B
bellard 已提交
1204
/* eqv & eqv. */
1205
GEN_LOGICAL2(eqv, 0x08, PPC_INTEGER);
B
bellard 已提交
1206
/* extsb & extsb. */
1207
GEN_LOGICAL1(extsb, 0x1D, PPC_INTEGER);
B
bellard 已提交
1208
/* extsh & extsh. */
1209
GEN_LOGICAL1(extsh, 0x1C, PPC_INTEGER);
B
bellard 已提交
1210
/* nand & nand. */
1211
GEN_LOGICAL2(nand, 0x0E, PPC_INTEGER);
B
bellard 已提交
1212
/* nor & nor. */
1213
GEN_LOGICAL2(nor, 0x03, PPC_INTEGER);
1214

B
bellard 已提交
1215
/* or & or. */
1216 1217
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
{
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
    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) {
        gen_op_load_gpr_T0(rs);
        if (rs != rb) {
            gen_op_load_gpr_T1(rb);
            gen_op_or();
        }
        gen_op_store_T0_gpr(ra);
        if (unlikely(Rc(ctx->opcode) != 0))
            gen_set_Rc0(ctx);
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_op_load_gpr_T0(rs);
        gen_set_Rc0(ctx);
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
#if defined(TARGET_PPC64)
    } else {
        switch (rs) {
        case 1:
            /* Set process priority to low */
            gen_op_store_pri(2);
            break;
        case 6:
            /* Set process priority to medium-low */
            gen_op_store_pri(3);
            break;
        case 2:
            /* Set process priority to normal */
            gen_op_store_pri(4);
            break;
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
#if !defined(CONFIG_USER_ONLY)
        case 31:
            if (ctx->supervisor > 0) {
                /* Set process priority to very low */
                gen_op_store_pri(1);
            }
            break;
        case 5:
            if (ctx->supervisor > 0) {
                /* Set process priority to medium-hight */
                gen_op_store_pri(5);
            }
            break;
        case 3:
            if (ctx->supervisor > 0) {
                /* Set process priority to high */
                gen_op_store_pri(6);
            }
            break;
        case 7:
            if (ctx->supervisor > 1) {
                /* Set process priority to very high */
                gen_op_store_pri(7);
            }
            break;
#endif
1277 1278 1279 1280 1281
        default:
            /* nop */
            break;
        }
#endif
1282 1283 1284
    }
}

B
bellard 已提交
1285
/* orc & orc. */
1286
GEN_LOGICAL2(orc, 0x0C, PPC_INTEGER);
B
bellard 已提交
1287
/* xor & xor. */
1288 1289 1290 1291 1292 1293 1294 1295
GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    /* Optimisation for "set to zero" case */
    if (rS(ctx->opcode) != rB(ctx->opcode)) {
        gen_op_load_gpr_T1(rB(ctx->opcode));
        gen_op_xor();
    } else {
1296
        gen_op_reset_T0();
1297 1298
    }
    gen_op_store_T0_gpr(rA(ctx->opcode));
1299 1300
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
1301
}
B
bellard 已提交
1302 1303 1304
/* ori */
GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1305
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1306

1307 1308
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
1309
        /* XXX: should handle special NOPs for POWER series */
1310
        return;
1311 1312 1313
    }
    gen_op_load_gpr_T0(rS(ctx->opcode));
    if (likely(uimm != 0))
B
bellard 已提交
1314
        gen_op_ori(uimm);
1315
    gen_op_store_T0_gpr(rA(ctx->opcode));
B
bellard 已提交
1316 1317 1318 1319
}
/* oris */
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1320
    target_ulong uimm = UIMM(ctx->opcode);
B
bellard 已提交
1321

1322 1323 1324
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
1325 1326 1327
    }
    gen_op_load_gpr_T0(rS(ctx->opcode));
    if (likely(uimm != 0))
B
bellard 已提交
1328
        gen_op_ori(uimm << 16);
1329
    gen_op_store_T0_gpr(rA(ctx->opcode));
B
bellard 已提交
1330 1331 1332 1333
}
/* xori */
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1334
    target_ulong uimm = UIMM(ctx->opcode);
1335 1336 1337 1338 1339

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
B
bellard 已提交
1340
    gen_op_load_gpr_T0(rS(ctx->opcode));
1341 1342
    if (likely(uimm != 0))
        gen_op_xori(uimm);
B
bellard 已提交
1343 1344 1345 1346 1347 1348
    gen_op_store_T0_gpr(rA(ctx->opcode));
}

/* xoris */
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1349
    target_ulong uimm = UIMM(ctx->opcode);
1350 1351 1352 1353 1354

    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
        /* NOP */
        return;
    }
B
bellard 已提交
1355
    gen_op_load_gpr_T0(rS(ctx->opcode));
1356 1357
    if (likely(uimm != 0))
        gen_op_xori(uimm << 16);
B
bellard 已提交
1358 1359 1360
    gen_op_store_T0_gpr(rA(ctx->opcode));
}

1361
/* popcntb : PowerPC 2.03 specification */
1362
GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB)
1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_popcntb_64();
    else
#endif
        gen_op_popcntb();
    gen_op_store_T0_gpr(rA(ctx->opcode));
}

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

B
bellard 已提交
1381 1382 1383 1384
/***                             Integer rotate                            ***/
/* rlwimi & rlwimi. */
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
1385 1386
    target_ulong mask;
    uint32_t mb, me, sh;
B
bellard 已提交
1387 1388 1389

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402
    sh = SH(ctx->opcode);
    if (likely(sh == 0)) {
        if (likely(mb == 0 && me == 31)) {
            gen_op_load_gpr_T0(rS(ctx->opcode));
            goto do_store;
        } else if (likely(mb == 31 && me == 0)) {
            gen_op_load_gpr_T0(rA(ctx->opcode));
            goto do_store;
        }
        gen_op_load_gpr_T0(rS(ctx->opcode));
        gen_op_load_gpr_T1(rA(ctx->opcode));
        goto do_mask;
    }
B
bellard 已提交
1403
    gen_op_load_gpr_T0(rS(ctx->opcode));
B
bellard 已提交
1404
    gen_op_load_gpr_T1(rA(ctx->opcode));
1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
    gen_op_rotli32_T0(SH(ctx->opcode));
 do_mask:
#if defined(TARGET_PPC64)
    mb += 32;
    me += 32;
#endif
    mask = MASK(mb, me);
    gen_op_andi_T0(mask);
    gen_op_andi_T1(~mask);
    gen_op_or();
 do_store:
B
bellard 已提交
1416
    gen_op_store_T0_gpr(rA(ctx->opcode));
1417 1418
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
B
bellard 已提交
1419 1420 1421 1422 1423
}
/* rlwinm & rlwinm. */
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    uint32_t mb, me, sh;
1424

B
bellard 已提交
1425 1426 1427 1428
    sh = SH(ctx->opcode);
    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
    gen_op_load_gpr_T0(rS(ctx->opcode));
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438
    if (likely(sh == 0)) {
        goto do_mask;
    }
    if (likely(mb == 0)) {
        if (likely(me == 31)) {
            gen_op_rotli32_T0(sh);
            goto do_store;
        } else if (likely(me == (31 - sh))) {
            gen_op_sli_T0(sh);
            goto do_store;
B
bellard 已提交
1439
        }
1440 1441 1442 1443
    } else if (likely(me == 31)) {
        if (likely(sh == (32 - mb))) {
            gen_op_srli_T0(mb);
            goto do_store;
B
bellard 已提交
1444 1445
        }
    }
1446 1447 1448 1449 1450 1451 1452 1453
    gen_op_rotli32_T0(sh);
 do_mask:
#if defined(TARGET_PPC64)
    mb += 32;
    me += 32;
#endif
    gen_op_andi_T0(MASK(mb, me));
 do_store:
B
bellard 已提交
1454
    gen_op_store_T0_gpr(rA(ctx->opcode));
1455 1456
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
B
bellard 已提交
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
}
/* rlwnm & rlwnm. */
GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
    uint32_t mb, me;

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
1467 1468 1469 1470 1471 1472 1473
    gen_op_rotl32_T0_T1();
    if (unlikely(mb != 0 || me != 31)) {
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
        gen_op_andi_T0(MASK(mb, me));
B
bellard 已提交
1474 1475
    }
    gen_op_store_T0_gpr(rA(ctx->opcode));
1476 1477
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
B
bellard 已提交
1478 1479
}

1480 1481
#if defined(TARGET_PPC64)
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
1482
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1483 1484 1485
{                                                                             \
    gen_##name(ctx, 0);                                                       \
}                                                                             \
1486 1487
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1488 1489 1490 1491
{                                                                             \
    gen_##name(ctx, 1);                                                       \
}
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
1492
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1493 1494 1495
{                                                                             \
    gen_##name(ctx, 0, 0);                                                    \
}                                                                             \
1496 1497
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1498 1499 1500
{                                                                             \
    gen_##name(ctx, 0, 1);                                                    \
}                                                                             \
1501 1502
GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1503 1504 1505
{                                                                             \
    gen_##name(ctx, 1, 0);                                                    \
}                                                                             \
1506 1507
GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000,   \
             PPC_64B)                                                         \
1508 1509 1510
{                                                                             \
    gen_##name(ctx, 1, 1);                                                    \
}
J
j_mayer 已提交
1511

1512
static always_inline void gen_andi_T0_64 (DisasContext *ctx, uint64_t mask)
1513 1514 1515 1516 1517 1518 1519
{
    if (mask >> 32)
        gen_op_andi_T0_64(mask >> 32, mask & 0xFFFFFFFF);
    else
        gen_op_andi_T0(mask);
}

1520
static always_inline void gen_andi_T1_64 (DisasContext *ctx, uint64_t mask)
1521 1522 1523 1524 1525 1526 1527
{
    if (mask >> 32)
        gen_op_andi_T1_64(mask >> 32, mask & 0xFFFFFFFF);
    else
        gen_op_andi_T1(mask);
}

1528 1529
static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
                                      uint32_t me, uint32_t sh)
J
j_mayer 已提交
1530 1531 1532 1533 1534 1535 1536
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    if (likely(sh == 0)) {
        goto do_mask;
    }
    if (likely(mb == 0)) {
        if (likely(me == 63)) {
1537
            gen_op_rotli64_T0(sh);
J
j_mayer 已提交
1538 1539 1540 1541 1542 1543 1544
            goto do_store;
        } else if (likely(me == (63 - sh))) {
            gen_op_sli_T0(sh);
            goto do_store;
        }
    } else if (likely(me == 63)) {
        if (likely(sh == (64 - mb))) {
1545
            gen_op_srli_T0_64(mb);
J
j_mayer 已提交
1546 1547 1548 1549 1550
            goto do_store;
        }
    }
    gen_op_rotli64_T0(sh);
 do_mask:
1551
    gen_andi_T0_64(ctx, MASK(mb, me));
J
j_mayer 已提交
1552 1553 1554 1555 1556
 do_store:
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}
1557
/* rldicl - rldicl. */
1558
static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1559
{
J
j_mayer 已提交
1560
    uint32_t sh, mb;
1561

J
j_mayer 已提交
1562 1563
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1564
    gen_rldinm(ctx, mb, 63, sh);
1565
}
J
j_mayer 已提交
1566
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1567
/* rldicr - rldicr. */
1568
static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1569
{
J
j_mayer 已提交
1570
    uint32_t sh, me;
1571

J
j_mayer 已提交
1572 1573
    sh = SH(ctx->opcode) | (shn << 5);
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1574
    gen_rldinm(ctx, 0, me, sh);
1575
}
J
j_mayer 已提交
1576
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1577
/* rldic - rldic. */
1578
static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1579
{
J
j_mayer 已提交
1580
    uint32_t sh, mb;
1581

J
j_mayer 已提交
1582 1583
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1584 1585 1586 1587
    gen_rldinm(ctx, mb, 63 - sh, sh);
}
GEN_PPC64_R4(rldic, 0x1E, 0x04);

1588 1589
static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
                                     uint32_t me)
J
j_mayer 已提交
1590 1591 1592 1593 1594
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_rotl64_T0_T1();
    if (unlikely(mb != 0 || me != 63)) {
1595
        gen_andi_T0_64(ctx, MASK(mb, me));
J
j_mayer 已提交
1596 1597 1598 1599
    }
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
1600
}
J
j_mayer 已提交
1601

1602
/* rldcl - rldcl. */
1603
static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1604
{
J
j_mayer 已提交
1605
    uint32_t mb;
1606

J
j_mayer 已提交
1607
    mb = MB(ctx->opcode) | (mbn << 5);
J
j_mayer 已提交
1608
    gen_rldnm(ctx, mb, 63);
1609
}
1610
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1611
/* rldcr - rldcr. */
1612
static always_inline void gen_rldcr (DisasContext *ctx, int men)
1613
{
J
j_mayer 已提交
1614
    uint32_t me;
1615

J
j_mayer 已提交
1616
    me = MB(ctx->opcode) | (men << 5);
J
j_mayer 已提交
1617
    gen_rldnm(ctx, 0, me);
1618
}
1619
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1620
/* rldimi - rldimi. */
1621
static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1622
{
J
j_mayer 已提交
1623
    uint64_t mask;
1624
    uint32_t sh, mb, me;
1625

J
j_mayer 已提交
1626 1627
    sh = SH(ctx->opcode) | (shn << 5);
    mb = MB(ctx->opcode) | (mbn << 5);
1628
    me = 63 - sh;
J
j_mayer 已提交
1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639
    if (likely(sh == 0)) {
        if (likely(mb == 0)) {
            gen_op_load_gpr_T0(rS(ctx->opcode));
            goto do_store;
        }
        gen_op_load_gpr_T0(rS(ctx->opcode));
        gen_op_load_gpr_T1(rA(ctx->opcode));
        goto do_mask;
    }
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rA(ctx->opcode));
1640
    gen_op_rotli64_T0(sh);
J
j_mayer 已提交
1641
 do_mask:
1642
    mask = MASK(mb, me);
1643 1644
    gen_andi_T0_64(ctx, mask);
    gen_andi_T1_64(ctx, ~mask);
J
j_mayer 已提交
1645 1646 1647 1648 1649
    gen_op_or();
 do_store:
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
1650
}
1651
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1652 1653
#endif

B
bellard 已提交
1654 1655
/***                             Integer shift                             ***/
/* slw & slw. */
1656
__GEN_LOGICAL2(slw, 0x18, 0x00, PPC_INTEGER);
B
bellard 已提交
1657
/* sraw & sraw. */
1658
__GEN_LOGICAL2(sraw, 0x18, 0x18, PPC_INTEGER);
B
bellard 已提交
1659 1660 1661
/* srawi & srawi. */
GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
{
1662
    int mb, me;
B
bellard 已提交
1663
    gen_op_load_gpr_T0(rS(ctx->opcode));
1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
    if (SH(ctx->opcode) != 0) {
        gen_op_move_T1_T0();
        mb = 32 - SH(ctx->opcode);
        me = 31;
#if defined(TARGET_PPC64)
        mb += 32;
        me += 32;
#endif
        gen_op_srawi(SH(ctx->opcode), MASK(mb, me));
    }
B
bellard 已提交
1674
    gen_op_store_T0_gpr(rA(ctx->opcode));
1675 1676
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
B
bellard 已提交
1677 1678
}
/* srw & srw. */
1679 1680 1681 1682 1683 1684 1685 1686
__GEN_LOGICAL2(srw, 0x18, 0x10, PPC_INTEGER);

#if defined(TARGET_PPC64)
/* sld & sld. */
__GEN_LOGICAL2(sld, 0x1B, 0x00, PPC_64B);
/* srad & srad. */
__GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B);
/* sradi & sradi. */
1687
static always_inline void gen_sradi (DisasContext *ctx, int n)
1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
{
    uint64_t mask;
    int sh, mb, me;

    gen_op_load_gpr_T0(rS(ctx->opcode));
    sh = SH(ctx->opcode) + (n << 5);
    if (sh != 0) {
        gen_op_move_T1_T0();
        mb = 64 - SH(ctx->opcode);
        me = 63;
        mask = MASK(mb, me);
        gen_op_sradi(sh, mask >> 32, mask);
    }
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}
1705
GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
1706 1707 1708
{
    gen_sradi(ctx, 0);
}
1709
GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
1710 1711 1712 1713 1714 1715
{
    gen_sradi(ctx, 1);
}
/* srd & srd. */
__GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
#endif
B
bellard 已提交
1716 1717

/***                       Floating-Point arithmetic                       ***/
1718
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
1719
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
1720
{                                                                             \
1721
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1722
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1723 1724
        return;                                                               \
    }                                                                         \
1725 1726 1727
    gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
    gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
    gen_op_load_fpr_FT2(rB(ctx->opcode));                                     \
1728
    gen_reset_fpstatus();                                                     \
1729 1730 1731 1732
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
1733
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
1734
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
1735 1736
}

1737 1738 1739
#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);
1740

1741 1742
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
1743
{                                                                             \
1744
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1745
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1746 1747
        return;                                                               \
    }                                                                         \
1748 1749
    gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
    gen_op_load_fpr_FT1(rB(ctx->opcode));                                     \
1750
    gen_reset_fpstatus();                                                     \
1751 1752 1753 1754
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
1755
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
1756
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
1757
}
1758 1759 1760
#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);
1761

1762 1763
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
1764
{                                                                             \
1765
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1766
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1767 1768
        return;                                                               \
    }                                                                         \
1769 1770
    gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
    gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
1771
    gen_reset_fpstatus();                                                     \
1772 1773 1774 1775
    gen_op_f##op();                                                           \
    if (isfloat) {                                                            \
        gen_op_frsp();                                                        \
    }                                                                         \
1776
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
1777
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
1778
}
1779 1780 1781
#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);
1782

1783
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
1784
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
1785
{                                                                             \
1786
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1787
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1788 1789
        return;                                                               \
    }                                                                         \
1790
    gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
1791
    gen_reset_fpstatus();                                                     \
1792 1793
    gen_op_f##name();                                                         \
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
1794
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
1795 1796
}

1797
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
1798
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)                        \
1799
{                                                                             \
1800
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1801
        GEN_EXCP_NO_FP(ctx);                                                  \
B
bellard 已提交
1802 1803
        return;                                                               \
    }                                                                         \
1804
    gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
1805
    gen_reset_fpstatus();                                                     \
1806 1807
    gen_op_f##name();                                                         \
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
1808
    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
B
bellard 已提交
1809 1810
}

1811
/* fadd - fadds */
1812
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
1813
/* fdiv - fdivs */
1814
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
1815
/* fmul - fmuls */
1816
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
B
bellard 已提交
1817

1818
/* fre */
1819
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
1820

1821
/* fres */
1822
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
B
bellard 已提交
1823

1824
/* frsqrte */
1825 1826 1827 1828 1829 1830 1831 1832
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);

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

1835
/* fsel */
1836
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
1837
/* fsub - fsubs */
1838
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
B
bellard 已提交
1839 1840
/* Optional: */
/* fsqrt */
1841
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1842
{
1843
    if (unlikely(!ctx->fpu_enabled)) {
1844
        GEN_EXCP_NO_FP(ctx);
1845 1846 1847
        return;
    }
    gen_op_load_fpr_FT0(rB(ctx->opcode));
1848
    gen_reset_fpstatus();
1849 1850
    gen_op_fsqrt();
    gen_op_store_FT0_fpr(rD(ctx->opcode));
1851
    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1852
}
B
bellard 已提交
1853

1854
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
B
bellard 已提交
1855
{
1856
    if (unlikely(!ctx->fpu_enabled)) {
1857
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1858 1859
        return;
    }
1860
    gen_op_load_fpr_FT0(rB(ctx->opcode));
1861
    gen_reset_fpstatus();
1862 1863
    gen_op_fsqrt();
    gen_op_frsp();
1864
    gen_op_store_FT0_fpr(rD(ctx->opcode));
1865
    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
B
bellard 已提交
1866 1867 1868
}

/***                     Floating-Point multiply-and-add                   ***/
1869
/* fmadd - fmadds */
1870
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
1871
/* fmsub - fmsubs */
1872
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
1873
/* fnmadd - fnmadds */
1874
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
1875
/* fnmsub - fnmsubs */
1876
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
B
bellard 已提交
1877 1878 1879

/***                     Floating-Point round & convert                    ***/
/* fctiw */
1880
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
1881
/* fctiwz */
1882
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
B
bellard 已提交
1883
/* frsp */
1884
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
J
j_mayer 已提交
1885 1886
#if defined(TARGET_PPC64)
/* fcfid */
1887
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
J
j_mayer 已提交
1888
/* fctid */
1889
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
J
j_mayer 已提交
1890
/* fctidz */
1891
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
J
j_mayer 已提交
1892
#endif
B
bellard 已提交
1893

1894
/* frin */
1895
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
1896
/* friz */
1897
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
1898
/* frip */
1899
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
1900
/* frim */
1901
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
1902

B
bellard 已提交
1903 1904
/***                         Floating-Point compare                        ***/
/* fcmpo */
1905
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
B
bellard 已提交
1906
{
1907
    if (unlikely(!ctx->fpu_enabled)) {
1908
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1909 1910
        return;
    }
1911 1912
    gen_op_load_fpr_FT0(rA(ctx->opcode));
    gen_op_load_fpr_FT1(rB(ctx->opcode));
1913
    gen_reset_fpstatus();
1914 1915
    gen_op_fcmpo();
    gen_op_store_T0_crf(crfD(ctx->opcode));
1916
    gen_op_float_check_status();
B
bellard 已提交
1917 1918 1919
}

/* fcmpu */
1920
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
B
bellard 已提交
1921
{
1922
    if (unlikely(!ctx->fpu_enabled)) {
1923
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1924 1925
        return;
    }
1926 1927
    gen_op_load_fpr_FT0(rA(ctx->opcode));
    gen_op_load_fpr_FT1(rB(ctx->opcode));
1928
    gen_reset_fpstatus();
1929 1930
    gen_op_fcmpu();
    gen_op_store_T0_crf(crfD(ctx->opcode));
1931
    gen_op_float_check_status();
B
bellard 已提交
1932 1933
}

1934 1935
/***                         Floating-point move                           ***/
/* fabs */
1936 1937
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
1938 1939

/* fmr  - fmr. */
1940
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
1941 1942
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
{
1943
    if (unlikely(!ctx->fpu_enabled)) {
1944
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1945 1946
        return;
    }
1947 1948
    gen_op_load_fpr_FT0(rB(ctx->opcode));
    gen_op_store_FT0_fpr(rD(ctx->opcode));
1949
    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
1950 1951 1952
}

/* fnabs */
1953 1954
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
1955
/* fneg */
1956 1957
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
1958

B
bellard 已提交
1959 1960 1961 1962
/***                  Floating-Point status & ctrl register                ***/
/* mcrfs */
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
{
1963 1964
    int bfa;

1965
    if (unlikely(!ctx->fpu_enabled)) {
1966
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1967 1968
        return;
    }
1969 1970 1971
    gen_optimize_fprf();
    bfa = 4 * (7 - crfS(ctx->opcode));
    gen_op_load_fpscr_T0(bfa);
B
bellard 已提交
1972
    gen_op_store_T0_crf(crfD(ctx->opcode));
1973
    gen_op_fpscr_resetbit(~(0xF << bfa));
B
bellard 已提交
1974 1975 1976 1977 1978
}

/* mffs */
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
{
1979
    if (unlikely(!ctx->fpu_enabled)) {
1980
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1981 1982
        return;
    }
1983 1984 1985
    gen_optimize_fprf();
    gen_reset_fpstatus();
    gen_op_load_fpscr_FT0();
B
bellard 已提交
1986
    gen_op_store_FT0_fpr(rD(ctx->opcode));
1987
    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
B
bellard 已提交
1988 1989 1990 1991 1992
}

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

1995
    if (unlikely(!ctx->fpu_enabled)) {
1996
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
1997 1998
        return;
    }
1999 2000 2001 2002 2003 2004 2005 2006 2007
    crb = 32 - (crbD(ctx->opcode) >> 2);
    gen_optimize_fprf();
    gen_reset_fpstatus();
    if (likely(crb != 30 && crb != 29))
        gen_op_fpscr_resetbit(~(1 << crb));
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_op_load_fpcc();
        gen_op_set_Rc0();
    }
B
bellard 已提交
2008 2009 2010 2011 2012
}

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

2015
    if (unlikely(!ctx->fpu_enabled)) {
2016
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2017 2018
        return;
    }
2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030
    crb = 32 - (crbD(ctx->opcode) >> 2);
    gen_optimize_fprf();
    gen_reset_fpstatus();
    /* XXX: we pretend we can only do IEEE floating-point computations */
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI))
        gen_op_fpscr_setbit(crb);
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_op_load_fpcc();
        gen_op_set_Rc0();
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2031 2032 2033 2034 2035
}

/* mtfsf */
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
{
2036
    if (unlikely(!ctx->fpu_enabled)) {
2037
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2038 2039
        return;
    }
2040
    gen_optimize_fprf();
B
bellard 已提交
2041
    gen_op_load_fpr_FT0(rB(ctx->opcode));
2042
    gen_reset_fpstatus();
2043
    gen_op_store_fpscr(FM(ctx->opcode));
2044 2045 2046 2047 2048 2049
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_op_load_fpcc();
        gen_op_set_Rc0();
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2050 2051 2052 2053 2054
}

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

2057
    if (unlikely(!ctx->fpu_enabled)) {
2058
        GEN_EXCP_NO_FP(ctx);
B
bellard 已提交
2059 2060
        return;
    }
2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072
    bf = crbD(ctx->opcode) >> 2;
    sh = 7 - bf;
    gen_optimize_fprf();
    gen_op_set_FT0(FPIMM(ctx->opcode) << (4 * sh));
    gen_reset_fpstatus();
    gen_op_store_fpscr(1 << sh);
    if (unlikely(Rc(ctx->opcode) != 0)) {
        gen_op_load_fpcc();
        gen_op_set_Rc0();
    }
    /* We can raise a differed exception */
    gen_op_float_check_status();
B
bellard 已提交
2073 2074
}

2075 2076
/***                           Addressing modes                            ***/
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2077 2078
static always_inline void gen_addr_imm_index (DisasContext *ctx,
                                              target_long maskl)
2079 2080 2081
{
    target_long simm = SIMM(ctx->opcode);

2082
    simm &= ~maskl;
2083
    if (rA(ctx->opcode) == 0) {
2084
        gen_set_T0(simm);
2085 2086 2087 2088 2089
    } else {
        gen_op_load_gpr_T0(rA(ctx->opcode));
        if (likely(simm != 0))
            gen_op_addi(simm);
    }
2090 2091 2092
#ifdef DEBUG_MEMORY_ACCESSES
    gen_op_print_mem_EA();
#endif
2093 2094
}

2095
static always_inline void gen_addr_reg_index (DisasContext *ctx)
2096 2097 2098 2099 2100 2101 2102 2103
{
    if (rA(ctx->opcode) == 0) {
        gen_op_load_gpr_T0(rB(ctx->opcode));
    } else {
        gen_op_load_gpr_T0(rA(ctx->opcode));
        gen_op_load_gpr_T1(rB(ctx->opcode));
        gen_op_add();
    }
2104 2105 2106
#ifdef DEBUG_MEMORY_ACCESSES
    gen_op_print_mem_EA();
#endif
2107 2108
}

2109
static always_inline void gen_addr_register (DisasContext *ctx)
2110 2111 2112 2113 2114 2115
{
    if (rA(ctx->opcode) == 0) {
        gen_op_reset_T0();
    } else {
        gen_op_load_gpr_T0(rA(ctx->opcode));
    }
2116 2117 2118
#ifdef DEBUG_MEMORY_ACCESSES
    gen_op_print_mem_EA();
#endif
2119 2120
}

2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131
#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
2132
#if defined(CONFIG_USER_ONLY)
2133
#if defined(TARGET_PPC64)
2134
#define NB_MEM_FUNCS 4
2135
#else
2136
#define NB_MEM_FUNCS 2
2137
#endif
2138 2139
#define GEN_MEM_FUNCS(name)                                                   \
    _GEN_MEM_FUNCS(name, raw)
2140
#else
2141
#if defined(TARGET_PPC64)
2142
#define NB_MEM_FUNCS 12
2143
#else
2144
#define NB_MEM_FUNCS 6
2145
#endif
2146 2147 2148 2149 2150 2151 2152 2153
#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])()
2154
/* Byte access routine are endian safe */
2155 2156 2157 2158 2159
#define gen_op_lbz_le_raw       gen_op_lbz_raw
#define gen_op_lbz_le_user      gen_op_lbz_user
#define gen_op_lbz_le_kernel    gen_op_lbz_kernel
#define gen_op_lbz_le_hypv      gen_op_lbz_hypv
#define gen_op_lbz_le_64_raw    gen_op_lbz_64_raw
2160
#define gen_op_lbz_le_64_user   gen_op_lbz_64_user
2161
#define gen_op_lbz_le_64_kernel gen_op_lbz_64_kernel
2162 2163 2164 2165 2166 2167 2168 2169 2170
#define gen_op_lbz_le_64_hypv   gen_op_lbz_64_hypv
#define gen_op_stb_le_raw       gen_op_stb_raw
#define gen_op_stb_le_user      gen_op_stb_user
#define gen_op_stb_le_kernel    gen_op_stb_kernel
#define gen_op_stb_le_hypv      gen_op_stb_hypv
#define gen_op_stb_le_64_raw    gen_op_stb_64_raw
#define gen_op_stb_le_64_user   gen_op_stb_64_user
#define gen_op_stb_le_64_kernel gen_op_stb_64_kernel
#define gen_op_stb_le_64_hypv   gen_op_stb_64_hypv
2171
#define OP_LD_TABLE(width)                                                    \
2172 2173
static GenOpFunc *gen_op_l##width[NB_MEM_FUNCS] = {                           \
    GEN_MEM_FUNCS(l##width),                                                  \
2174 2175
};
#define OP_ST_TABLE(width)                                                    \
2176 2177
static GenOpFunc *gen_op_st##width[NB_MEM_FUNCS] = {                          \
    GEN_MEM_FUNCS(st##width),                                                 \
2178
};
2179

2180 2181
#define GEN_LD(width, opc, type)                                              \
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
B
bellard 已提交
2182
{                                                                             \
J
j_mayer 已提交
2183
    gen_addr_imm_index(ctx, 0);                                               \
2184
    op_ldst(l##width);                                                        \
B
bellard 已提交
2185 2186 2187
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
}

2188 2189
#define GEN_LDU(width, opc, type)                                             \
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
B
bellard 已提交
2190
{                                                                             \
2191 2192
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2193
        GEN_EXCP_INVAL(ctx);                                                  \
2194
        return;                                                               \
2195
    }                                                                         \
J
j_mayer 已提交
2196
    if (type == PPC_64B)                                                      \
2197
        gen_addr_imm_index(ctx, 0x03);                                        \
J
j_mayer 已提交
2198 2199
    else                                                                      \
        gen_addr_imm_index(ctx, 0);                                           \
2200
    op_ldst(l##width);                                                        \
B
bellard 已提交
2201 2202 2203 2204
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
}

2205 2206
#define GEN_LDUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2207
{                                                                             \
2208 2209
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2210
        GEN_EXCP_INVAL(ctx);                                                  \
2211
        return;                                                               \
2212
    }                                                                         \
2213
    gen_addr_reg_index(ctx);                                                  \
2214
    op_ldst(l##width);                                                        \
B
bellard 已提交
2215 2216 2217 2218
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
}

2219 2220
#define GEN_LDX(width, opc2, opc3, type)                                      \
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
B
bellard 已提交
2221
{                                                                             \
2222
    gen_addr_reg_index(ctx);                                                  \
2223
    op_ldst(l##width);                                                        \
B
bellard 已提交
2224 2225 2226
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
}

2227
#define GEN_LDS(width, op, type)                                              \
2228
OP_LD_TABLE(width);                                                           \
2229 2230 2231 2232
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 已提交
2233 2234

/* lbz lbzu lbzux lbzx */
2235
GEN_LDS(bz, 0x02, PPC_INTEGER);
B
bellard 已提交
2236
/* lha lhau lhaux lhax */
2237
GEN_LDS(ha, 0x0A, PPC_INTEGER);
B
bellard 已提交
2238
/* lhz lhzu lhzux lhzx */
2239
GEN_LDS(hz, 0x08, PPC_INTEGER);
B
bellard 已提交
2240
/* lwz lwzu lwzux lwzx */
2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257
GEN_LDS(wz, 0x00, PPC_INTEGER);
#if defined(TARGET_PPC64)
OP_LD_TABLE(wa);
OP_LD_TABLE(d);
/* lwaux */
GEN_LDUX(wa, 0x15, 0x0B, PPC_64B);
/* lwax */
GEN_LDX(wa, 0x15, 0x0A, PPC_64B);
/* ldux */
GEN_LDUX(d, 0x15, 0x01, PPC_64B);
/* ldx */
GEN_LDX(d, 0x15, 0x00, PPC_64B);
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
{
    if (Rc(ctx->opcode)) {
        if (unlikely(rA(ctx->opcode) == 0 ||
                     rA(ctx->opcode) == rD(ctx->opcode))) {
2258
            GEN_EXCP_INVAL(ctx);
2259 2260 2261
            return;
        }
    }
2262
    gen_addr_imm_index(ctx, 0x03);
2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273
    if (ctx->opcode & 0x02) {
        /* lwa (lwau is undefined) */
        op_ldst(lwa);
    } else {
        /* ld - ldu */
        op_ldst(ld);
    }
    gen_op_store_T1_gpr(rD(ctx->opcode));
    if (Rc(ctx->opcode))
        gen_op_store_T0_gpr(rA(ctx->opcode));
}
2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305
/* lq */
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    int ra, rd;

    /* Restore CPU state */
    if (unlikely(ctx->supervisor == 0)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
    ra = rA(ctx->opcode);
    rd = rD(ctx->opcode);
    if (unlikely((rd & 1) || rd == ra)) {
        GEN_EXCP_INVAL(ctx);
        return;
    }
    if (unlikely(ctx->mem_idx & 1)) {
        /* Little-endian mode is not handled */
        GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
        return;
    }
    gen_addr_imm_index(ctx, 0x0F);
    op_ldst(ld);
    gen_op_store_T1_gpr(rd);
    gen_op_addi(8);
    op_ldst(ld);
    gen_op_store_T1_gpr(rd + 1);
#endif
}
2306
#endif
B
bellard 已提交
2307 2308

/***                              Integer store                            ***/
2309 2310
#define GEN_ST(width, opc, type)                                              \
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
B
bellard 已提交
2311
{                                                                             \
J
j_mayer 已提交
2312
    gen_addr_imm_index(ctx, 0);                                               \
2313 2314
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
    op_ldst(st##width);                                                       \
B
bellard 已提交
2315 2316
}

2317 2318
#define GEN_STU(width, opc, type)                                             \
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
B
bellard 已提交
2319
{                                                                             \
2320
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2321
        GEN_EXCP_INVAL(ctx);                                                  \
2322
        return;                                                               \
2323
    }                                                                         \
J
j_mayer 已提交
2324
    if (type == PPC_64B)                                                      \
2325
        gen_addr_imm_index(ctx, 0x03);                                        \
J
j_mayer 已提交
2326 2327
    else                                                                      \
        gen_addr_imm_index(ctx, 0);                                           \
B
bellard 已提交
2328
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
2329
    op_ldst(st##width);                                                       \
B
bellard 已提交
2330 2331 2332
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
}

2333 2334
#define GEN_STUX(width, opc2, opc3, type)                                     \
GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                \
B
bellard 已提交
2335
{                                                                             \
2336
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2337
        GEN_EXCP_INVAL(ctx);                                                  \
2338
        return;                                                               \
2339
    }                                                                         \
2340
    gen_addr_reg_index(ctx);                                                  \
2341 2342
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
    op_ldst(st##width);                                                       \
B
bellard 已提交
2343 2344 2345
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
}

2346 2347
#define GEN_STX(width, opc2, opc3, type)                                      \
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2348
{                                                                             \
2349
    gen_addr_reg_index(ctx);                                                  \
2350 2351
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
    op_ldst(st##width);                                                       \
B
bellard 已提交
2352 2353
}

2354
#define GEN_STS(width, op, type)                                              \
2355
OP_ST_TABLE(width);                                                           \
2356 2357 2358 2359
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 已提交
2360 2361

/* stb stbu stbux stbx */
2362
GEN_STS(b, 0x06, PPC_INTEGER);
B
bellard 已提交
2363
/* sth sthu sthux sthx */
2364
GEN_STS(h, 0x0C, PPC_INTEGER);
B
bellard 已提交
2365
/* stw stwu stwux stwx */
2366 2367 2368
GEN_STS(w, 0x04, PPC_INTEGER);
#if defined(TARGET_PPC64)
OP_ST_TABLE(d);
J
j_mayer 已提交
2369 2370
GEN_STUX(d, 0x15, 0x05, PPC_64B);
GEN_STX(d, 0x15, 0x04, PPC_64B);
2371
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2372
{
2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385
    int rs;

    rs = rS(ctx->opcode);
    if ((ctx->opcode & 0x3) == 0x2) {
#if defined(CONFIG_USER_ONLY)
        GEN_EXCP_PRIVOPC(ctx);
#else
        /* stq */
        if (unlikely(ctx->supervisor == 0)) {
            GEN_EXCP_PRIVOPC(ctx);
            return;
        }
        if (unlikely(rs & 1)) {
2386
            GEN_EXCP_INVAL(ctx);
2387 2388
            return;
        }
2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413
        if (unlikely(ctx->mem_idx & 1)) {
            /* Little-endian mode is not handled */
            GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
            return;
        }
        gen_addr_imm_index(ctx, 0x03);
        gen_op_load_gpr_T1(rs);
        op_ldst(std);
        gen_op_addi(8);
        gen_op_load_gpr_T1(rs + 1);
        op_ldst(std);
#endif
    } else {
        /* std / stdu */
        if (Rc(ctx->opcode)) {
            if (unlikely(rA(ctx->opcode) == 0)) {
                GEN_EXCP_INVAL(ctx);
                return;
            }
        }
        gen_addr_imm_index(ctx, 0x03);
        gen_op_load_gpr_T1(rs);
        op_ldst(std);
        if (Rc(ctx->opcode))
            gen_op_store_T0_gpr(rA(ctx->opcode));
2414 2415 2416
    }
}
#endif
B
bellard 已提交
2417 2418
/***                Integer load and store with byte reverse               ***/
/* lhbrx */
2419
OP_LD_TABLE(hbr);
2420
GEN_LDX(hbr, 0x16, 0x18, PPC_INTEGER);
B
bellard 已提交
2421
/* lwbrx */
2422
OP_LD_TABLE(wbr);
2423
GEN_LDX(wbr, 0x16, 0x10, PPC_INTEGER);
B
bellard 已提交
2424
/* sthbrx */
2425
OP_ST_TABLE(hbr);
2426
GEN_STX(hbr, 0x16, 0x1C, PPC_INTEGER);
B
bellard 已提交
2427
/* stwbrx */
2428
OP_ST_TABLE(wbr);
2429
GEN_STX(wbr, 0x16, 0x14, PPC_INTEGER);
B
bellard 已提交
2430 2431

/***                    Integer load and store multiple                    ***/
2432
#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
2433 2434
static GenOpFunc1 *gen_op_lmw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lmw),
2435
};
2436 2437
static GenOpFunc1 *gen_op_stmw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stmw),
2438
};
2439

B
bellard 已提交
2440 2441 2442
/* lmw */
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
2443
    /* NIP cannot be restored if the memory exception comes from an helper */
2444
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
2445
    gen_addr_imm_index(ctx, 0);
2446
    op_ldstm(lmw, rD(ctx->opcode));
B
bellard 已提交
2447 2448 2449 2450 2451
}

/* stmw */
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
{
2452
    /* NIP cannot be restored if the memory exception comes from an helper */
2453
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
2454
    gen_addr_imm_index(ctx, 0);
2455
    op_ldstm(stmw, rS(ctx->opcode));
B
bellard 已提交
2456 2457 2458
}

/***                    Integer load and store strings                     ***/
2459 2460
#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)
2461 2462 2463 2464 2465 2466 2467 2468 2469
/* 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
2470 2471
static GenOpFunc1 *gen_op_lswi[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lswi),
2472
};
2473 2474 2475 2476 2477 2478 2479 2480
#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
2481 2482
static GenOpFunc3 *gen_op_lswx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lswx),
2483
};
2484 2485 2486 2487 2488 2489 2490 2491
#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
2492 2493
static GenOpFunc1 *gen_op_stsw[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stsw),
2494 2495
};

B
bellard 已提交
2496
/* lswi */
2497
/* PowerPC32 specification says we must generate an exception if
2498 2499 2500 2501
 * 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...
 */
2502
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
B
bellard 已提交
2503 2504 2505
{
    int nb = NB(ctx->opcode);
    int start = rD(ctx->opcode);
2506
    int ra = rA(ctx->opcode);
B
bellard 已提交
2507 2508 2509 2510 2511
    int nr;

    if (nb == 0)
        nb = 32;
    nr = nb / 4;
2512 2513 2514
    if (unlikely(((start + nr) > 32  &&
                  start <= ra && (start + nr - 32) > ra) ||
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
2515 2516
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
2517
        return;
B
bellard 已提交
2518
    }
2519
    /* NIP cannot be restored if the memory exception comes from an helper */
2520
    gen_update_nip(ctx, ctx->nip - 4);
2521 2522
    gen_addr_register(ctx);
    gen_op_set_T1(nb);
2523
    op_ldsts(lswi, start);
B
bellard 已提交
2524 2525 2526
}

/* lswx */
2527
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
B
bellard 已提交
2528
{
2529 2530 2531
    int ra = rA(ctx->opcode);
    int rb = rB(ctx->opcode);

2532
    /* NIP cannot be restored if the memory exception comes from an helper */
2533
    gen_update_nip(ctx, ctx->nip - 4);
2534
    gen_addr_reg_index(ctx);
2535 2536
    if (ra == 0) {
        ra = rb;
B
bellard 已提交
2537
    }
2538 2539
    gen_op_load_xer_bc();
    op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
B
bellard 已提交
2540 2541 2542
}

/* stswi */
2543
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
B
bellard 已提交
2544
{
B
bellard 已提交
2545 2546
    int nb = NB(ctx->opcode);

2547
    /* NIP cannot be restored if the memory exception comes from an helper */
2548
    gen_update_nip(ctx, ctx->nip - 4);
2549
    gen_addr_register(ctx);
B
bellard 已提交
2550 2551 2552
    if (nb == 0)
        nb = 32;
    gen_op_set_T1(nb);
2553
    op_ldsts(stsw, rS(ctx->opcode));
B
bellard 已提交
2554 2555 2556
}

/* stswx */
2557
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
B
bellard 已提交
2558
{
2559
    /* NIP cannot be restored if the memory exception comes from an helper */
2560
    gen_update_nip(ctx, ctx->nip - 4);
2561 2562
    gen_addr_reg_index(ctx);
    gen_op_load_xer_bc();
2563
    op_ldsts(stsw, rS(ctx->opcode));
B
bellard 已提交
2564 2565 2566 2567
}

/***                        Memory synchronisation                         ***/
/* eieio */
2568
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
B
bellard 已提交
2569 2570 2571 2572
{
}

/* isync */
2573
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
B
bellard 已提交
2574
{
2575
    GEN_STOP(ctx);
B
bellard 已提交
2576 2577
}

2578 2579
#define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
2580 2581
static GenOpFunc *gen_op_lwarx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(lwarx),
2582
};
2583 2584
static GenOpFunc *gen_op_stwcx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stwcx),
B
bellard 已提交
2585
};
2586

2587
/* lwarx */
2588
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
B
bellard 已提交
2589
{
2590 2591
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2592
    gen_addr_reg_index(ctx);
B
bellard 已提交
2593
    op_lwarx();
B
bellard 已提交
2594 2595 2596 2597
    gen_op_store_T1_gpr(rD(ctx->opcode));
}

/* stwcx. */
2598
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
B
bellard 已提交
2599
{
2600 2601
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
2602
    gen_addr_reg_index(ctx);
2603 2604
    gen_op_load_gpr_T1(rS(ctx->opcode));
    op_stwcx();
B
bellard 已提交
2605 2606
}

J
j_mayer 已提交
2607 2608 2609
#if defined(TARGET_PPC64)
#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
2610 2611
static GenOpFunc *gen_op_ldarx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(ldarx),
J
j_mayer 已提交
2612
};
2613 2614
static GenOpFunc *gen_op_stdcx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(stdcx),
J
j_mayer 已提交
2615 2616 2617
};

/* ldarx */
2618
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
J
j_mayer 已提交
2619
{
2620 2621
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
2622 2623 2624 2625 2626 2627
    gen_addr_reg_index(ctx);
    op_ldarx();
    gen_op_store_T1_gpr(rD(ctx->opcode));
}

/* stdcx. */
2628
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
J
j_mayer 已提交
2629
{
2630 2631
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
2632 2633 2634 2635 2636 2637
    gen_addr_reg_index(ctx);
    gen_op_load_gpr_T1(rS(ctx->opcode));
    op_stdcx();
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
2638
/* sync */
2639
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
B
bellard 已提交
2640 2641 2642
{
}

2643 2644 2645 2646
/* wait */
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
{
    /* Stop translation, as the CPU is supposed to sleep from now */
2647 2648
    gen_op_wait();
    GEN_EXCP(ctx, EXCP_HLT, 1);
2649 2650
}

B
bellard 已提交
2651
/***                         Floating-point load                           ***/
2652 2653
#define GEN_LDF(width, opc, type)                                             \
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
B
bellard 已提交
2654
{                                                                             \
2655
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2656
        GEN_EXCP_NO_FP(ctx);                                                  \
2657 2658
        return;                                                               \
    }                                                                         \
J
j_mayer 已提交
2659
    gen_addr_imm_index(ctx, 0);                                               \
2660
    op_ldst(l##width);                                                        \
2661
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
B
bellard 已提交
2662 2663
}

2664 2665
#define GEN_LDUF(width, opc, type)                                            \
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
B
bellard 已提交
2666
{                                                                             \
2667
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2668
        GEN_EXCP_NO_FP(ctx);                                                  \
2669 2670
        return;                                                               \
    }                                                                         \
2671
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2672
        GEN_EXCP_INVAL(ctx);                                                  \
2673
        return;                                                               \
2674
    }                                                                         \
J
j_mayer 已提交
2675
    gen_addr_imm_index(ctx, 0);                                               \
2676
    op_ldst(l##width);                                                        \
2677
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
B
bellard 已提交
2678 2679 2680
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
}

2681 2682
#define GEN_LDUXF(width, opc, type)                                           \
GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                  \
B
bellard 已提交
2683
{                                                                             \
2684
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2685
        GEN_EXCP_NO_FP(ctx);                                                  \
2686 2687
        return;                                                               \
    }                                                                         \
2688
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2689
        GEN_EXCP_INVAL(ctx);                                                  \
2690
        return;                                                               \
2691
    }                                                                         \
2692
    gen_addr_reg_index(ctx);                                                  \
2693
    op_ldst(l##width);                                                        \
2694
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
B
bellard 已提交
2695 2696 2697
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
}

2698 2699
#define GEN_LDXF(width, opc2, opc3, type)                                     \
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
B
bellard 已提交
2700
{                                                                             \
2701
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2702
        GEN_EXCP_NO_FP(ctx);                                                  \
2703 2704
        return;                                                               \
    }                                                                         \
2705
    gen_addr_reg_index(ctx);                                                  \
2706
    op_ldst(l##width);                                                        \
2707
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
B
bellard 已提交
2708 2709
}

2710
#define GEN_LDFS(width, op, type)                                             \
2711
OP_LD_TABLE(width);                                                           \
2712 2713 2714 2715
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 已提交
2716 2717

/* lfd lfdu lfdux lfdx */
2718
GEN_LDFS(fd, 0x12, PPC_FLOAT);
B
bellard 已提交
2719
/* lfs lfsu lfsux lfsx */
2720
GEN_LDFS(fs, 0x10, PPC_FLOAT);
B
bellard 已提交
2721 2722

/***                         Floating-point store                          ***/
2723 2724
#define GEN_STF(width, opc, type)                                             \
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
B
bellard 已提交
2725
{                                                                             \
2726
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2727
        GEN_EXCP_NO_FP(ctx);                                                  \
2728 2729
        return;                                                               \
    }                                                                         \
J
j_mayer 已提交
2730
    gen_addr_imm_index(ctx, 0);                                               \
2731
    gen_op_load_fpr_FT0(rS(ctx->opcode));                                     \
2732
    op_ldst(st##width);                                                       \
B
bellard 已提交
2733 2734
}

2735 2736
#define GEN_STUF(width, opc, type)                                            \
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
B
bellard 已提交
2737
{                                                                             \
2738
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2739
        GEN_EXCP_NO_FP(ctx);                                                  \
2740 2741
        return;                                                               \
    }                                                                         \
2742
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2743
        GEN_EXCP_INVAL(ctx);                                                  \
2744
        return;                                                               \
2745
    }                                                                         \
J
j_mayer 已提交
2746
    gen_addr_imm_index(ctx, 0);                                               \
2747
    gen_op_load_fpr_FT0(rS(ctx->opcode));                                     \
2748
    op_ldst(st##width);                                                       \
B
bellard 已提交
2749 2750 2751
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
}

2752 2753
#define GEN_STUXF(width, opc, type)                                           \
GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                 \
B
bellard 已提交
2754
{                                                                             \
2755
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2756
        GEN_EXCP_NO_FP(ctx);                                                  \
2757 2758
        return;                                                               \
    }                                                                         \
2759
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2760
        GEN_EXCP_INVAL(ctx);                                                  \
2761
        return;                                                               \
2762
    }                                                                         \
2763 2764
    gen_addr_reg_index(ctx);                                                  \
    gen_op_load_fpr_FT0(rS(ctx->opcode));                                     \
2765
    op_ldst(st##width);                                                       \
B
bellard 已提交
2766 2767 2768
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
}

2769 2770
#define GEN_STXF(width, opc2, opc3, type)                                     \
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
B
bellard 已提交
2771
{                                                                             \
2772
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2773
        GEN_EXCP_NO_FP(ctx);                                                  \
2774 2775
        return;                                                               \
    }                                                                         \
2776 2777
    gen_addr_reg_index(ctx);                                                  \
    gen_op_load_fpr_FT0(rS(ctx->opcode));                                     \
2778
    op_ldst(st##width);                                                       \
B
bellard 已提交
2779 2780
}

2781
#define GEN_STFS(width, op, type)                                             \
2782
OP_ST_TABLE(width);                                                           \
2783 2784 2785 2786
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 已提交
2787 2788

/* stfd stfdu stfdux stfdx */
2789
GEN_STFS(fd, 0x16, PPC_FLOAT);
B
bellard 已提交
2790
/* stfs stfsu stfsux stfsx */
2791
GEN_STFS(fs, 0x14, PPC_FLOAT);
B
bellard 已提交
2792 2793 2794

/* Optional: */
/* stfiwx */
J
j_mayer 已提交
2795 2796
OP_ST_TABLE(fiw);
GEN_STXF(fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
B
bellard 已提交
2797 2798

/***                                Branch                                 ***/
2799 2800
static always_inline void gen_goto_tb (DisasContext *ctx, int n,
                                       target_ulong dest)
2801 2802 2803
{
    TranslationBlock *tb;
    tb = ctx->tb;
B
bellard 已提交
2804
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2805
        likely(!ctx->singlestep_enabled)) {
B
bellard 已提交
2806
        tcg_gen_goto_tb(n);
2807 2808 2809 2810 2811 2812 2813
        gen_set_T1(dest);
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_b_T1_64();
        else
#endif
            gen_op_b_T1();
B
bellard 已提交
2814
        tcg_gen_exit_tb((long)tb + n);
2815
    } else {
2816 2817 2818 2819 2820 2821 2822
        gen_set_T1(dest);
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_b_T1_64();
        else
#endif
            gen_op_b_T1();
2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836
        if (unlikely(ctx->singlestep_enabled)) {
            if ((ctx->singlestep_enabled &
                 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
                ctx->exception == POWERPC_EXCP_BRANCH) {
                target_ulong tmp = ctx->nip;
                ctx->nip = dest;
                GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0);
                ctx->nip = tmp;
            }
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
                gen_update_nip(ctx, dest);
                gen_op_debug();
            }
        }
B
bellard 已提交
2837
        tcg_gen_exit_tb(0);
2838
    }
B
bellard 已提交
2839 2840
}

2841
static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
2842 2843 2844 2845 2846 2847 2848 2849 2850
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode != 0 && (nip >> 32))
        gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
    else
#endif
        gen_op_setlr(ctx->nip);
}

B
bellard 已提交
2851 2852 2853
/* b ba bl bla */
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
2854
    target_ulong li, target;
B
bellard 已提交
2855

2856
    ctx->exception = POWERPC_EXCP_BRANCH;
B
bellard 已提交
2857
    /* sign extend LI */
2858
#if defined(TARGET_PPC64)
2859 2860 2861
    if (ctx->sf_mode)
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
    else
2862
#endif
2863
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
2864
    if (likely(AA(ctx->opcode) == 0))
B
bellard 已提交
2865
        target = ctx->nip + li - 4;
B
bellard 已提交
2866
    else
2867
        target = li;
2868
#if defined(TARGET_PPC64)
2869 2870
    if (!ctx->sf_mode)
        target = (uint32_t)target;
2871
#endif
2872 2873
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
2874
    gen_goto_tb(ctx, 0, target);
B
bellard 已提交
2875 2876
}

2877 2878 2879 2880
#define BCOND_IM  0
#define BCOND_LR  1
#define BCOND_CTR 2

2881
static always_inline void gen_bcond (DisasContext *ctx, int type)
2882
{
2883 2884
    target_ulong target = 0;
    target_ulong li;
2885 2886 2887
    uint32_t bo = BO(ctx->opcode);
    uint32_t bi = BI(ctx->opcode);
    uint32_t mask;
2888

2889
    ctx->exception = POWERPC_EXCP_BRANCH;
2890
    if ((bo & 0x4) == 0)
2891
        gen_op_dec_ctr();
2892 2893
    switch(type) {
    case BCOND_IM:
2894 2895
        li = (target_long)((int16_t)(BD(ctx->opcode)));
        if (likely(AA(ctx->opcode) == 0)) {
B
bellard 已提交
2896
            target = ctx->nip + li - 4;
2897 2898 2899
        } else {
            target = li;
        }
2900 2901 2902 2903
#if defined(TARGET_PPC64)
        if (!ctx->sf_mode)
            target = (uint32_t)target;
#endif
2904 2905 2906 2907 2908 2909 2910 2911 2912
        break;
    case BCOND_CTR:
        gen_op_movl_T1_ctr();
        break;
    default:
    case BCOND_LR:
        gen_op_movl_T1_lr();
        break;
    }
2913 2914
    if (LK(ctx->opcode))
        gen_setlr(ctx, ctx->nip);
2915
    if (bo & 0x10) {
2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932
        /* No CR condition */
        switch (bo & 0x6) {
        case 0:
#if defined(TARGET_PPC64)
            if (ctx->sf_mode)
                gen_op_test_ctr_64();
            else
#endif
                gen_op_test_ctr();
            break;
        case 2:
#if defined(TARGET_PPC64)
            if (ctx->sf_mode)
                gen_op_test_ctrz_64();
            else
#endif
                gen_op_test_ctrz();
2933 2934
            break;
        default:
2935 2936
        case 4:
        case 6:
2937
            if (type == BCOND_IM) {
2938
                gen_goto_tb(ctx, 0, target);
2939
                return;
2940
            } else {
2941 2942 2943 2944 2945 2946
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_b_T1_64();
                else
#endif
                    gen_op_b_T1();
2947
                goto no_test;
2948
            }
2949
            break;
2950
        }
2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974
    } else {
        mask = 1 << (3 - (bi & 0x03));
        gen_op_load_crf_T0(bi >> 2);
        if (bo & 0x8) {
            switch (bo & 0x6) {
            case 0:
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_test_ctr_true_64(mask);
                else
#endif
                    gen_op_test_ctr_true(mask);
                break;
            case 2:
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_test_ctrz_true_64(mask);
                else
#endif
                    gen_op_test_ctrz_true(mask);
                break;
            default:
            case 4:
            case 6:
2975
                gen_op_test_true(mask);
2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
                break;
            }
        } else {
            switch (bo & 0x6) {
            case 0:
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_test_ctr_false_64(mask);
                else
#endif
                    gen_op_test_ctr_false(mask);
2987
                break;
2988 2989 2990 2991 2992 2993 2994 2995
            case 2:
#if defined(TARGET_PPC64)
                if (ctx->sf_mode)
                    gen_op_test_ctrz_false_64(mask);
                else
#endif
                    gen_op_test_ctrz_false(mask);
                break;
2996
            default:
2997 2998
            case 4:
            case 6:
2999
                gen_op_test_false(mask);
3000 3001 3002 3003
                break;
            }
        }
    }
3004
    if (type == BCOND_IM) {
B
bellard 已提交
3005 3006
        int l1 = gen_new_label();
        gen_op_jz_T0(l1);
3007
        gen_goto_tb(ctx, 0, target);
B
bellard 已提交
3008
        gen_set_label(l1);
3009
        gen_goto_tb(ctx, 1, ctx->nip);
3010
    } else {
3011 3012 3013 3014 3015 3016
#if defined(TARGET_PPC64)
        if (ctx->sf_mode)
            gen_op_btest_T1_64(ctx->nip >> 32, ctx->nip);
        else
#endif
            gen_op_btest_T1(ctx->nip);
3017
    no_test:
3018 3019
        if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
            gen_update_nip(ctx, ctx->nip);
J
j_mayer 已提交
3020
            gen_op_debug();
3021
        }
B
bellard 已提交
3022
        tcg_gen_exit_tb(0);
J
j_mayer 已提交
3023
    }
3024 3025 3026
}

GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3027
{
3028 3029 3030 3031
    gen_bcond(ctx, BCOND_IM);
}

GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3032
{
3033 3034 3035 3036
    gen_bcond(ctx, BCOND_CTR);
}

GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3037
{
3038 3039
    gen_bcond(ctx, BCOND_LR);
}
B
bellard 已提交
3040 3041 3042 3043 3044

/***                      Condition register logical                       ***/
#define GEN_CRLOGIC(op, opc)                                                  \
GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)                 \
{                                                                             \
3045 3046
    uint8_t bitmask;                                                          \
    int sh;                                                                   \
B
bellard 已提交
3047
    gen_op_load_crf_T0(crbA(ctx->opcode) >> 2);                               \
3048 3049 3050 3051 3052
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
        gen_op_srli_T0(sh);                                                   \
    else if (sh < 0)                                                          \
        gen_op_sli_T0(-sh);                                                   \
B
bellard 已提交
3053
    gen_op_load_crf_T1(crbB(ctx->opcode) >> 2);                               \
3054 3055 3056 3057 3058
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
    if (sh > 0)                                                               \
        gen_op_srli_T1(sh);                                                   \
    else if (sh < 0)                                                          \
        gen_op_sli_T1(-sh);                                                   \
B
bellard 已提交
3059
    gen_op_##op();                                                            \
3060 3061
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
    gen_op_andi_T0(bitmask);                                                  \
B
bellard 已提交
3062
    gen_op_load_crf_T1(crbD(ctx->opcode) >> 2);                               \
3063 3064 3065
    gen_op_andi_T1(~bitmask);                                                 \
    gen_op_or();                                                              \
    gen_op_store_T0_crf(crbD(ctx->opcode) >> 2);                              \
B
bellard 已提交
3066 3067 3068
}

/* crand */
3069
GEN_CRLOGIC(and, 0x08);
B
bellard 已提交
3070
/* crandc */
3071
GEN_CRLOGIC(andc, 0x04);
B
bellard 已提交
3072
/* creqv */
3073
GEN_CRLOGIC(eqv, 0x09);
B
bellard 已提交
3074
/* crnand */
3075
GEN_CRLOGIC(nand, 0x07);
B
bellard 已提交
3076
/* crnor */
3077
GEN_CRLOGIC(nor, 0x01);
B
bellard 已提交
3078
/* cror */
3079
GEN_CRLOGIC(or, 0x0E);
B
bellard 已提交
3080
/* crorc */
3081
GEN_CRLOGIC(orc, 0x0D);
B
bellard 已提交
3082
/* crxor */
3083
GEN_CRLOGIC(xor, 0x06);
B
bellard 已提交
3084 3085 3086 3087 3088 3089 3090 3091 3092
/* mcrf */
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
{
    gen_op_load_crf_T0(crfS(ctx->opcode));
    gen_op_store_T0_crf(crfD(ctx->opcode));
}

/***                           System linkage                              ***/
/* rfi (supervisor only) */
3093
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
B
bellard 已提交
3094
{
3095
#if defined(CONFIG_USER_ONLY)
3096
    GEN_EXCP_PRIVOPC(ctx);
3097 3098
#else
    /* Restore CPU state */
3099
    if (unlikely(!ctx->supervisor)) {
3100
        GEN_EXCP_PRIVOPC(ctx);
3101
        return;
3102
    }
3103
    gen_op_rfi();
3104
    GEN_SYNC(ctx);
3105
#endif
B
bellard 已提交
3106 3107
}

J
j_mayer 已提交
3108
#if defined(TARGET_PPC64)
3109
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
J
j_mayer 已提交
3110 3111
{
#if defined(CONFIG_USER_ONLY)
3112
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3113 3114 3115
#else
    /* Restore CPU state */
    if (unlikely(!ctx->supervisor)) {
3116
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3117 3118
        return;
    }
3119
    gen_op_rfid();
3120
    GEN_SYNC(ctx);
J
j_mayer 已提交
3121 3122 3123
#endif
}

J
j_mayer 已提交
3124
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139
{
#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 已提交
3140
/* sc */
3141 3142 3143 3144 3145
#if defined(CONFIG_USER_ONLY)
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
#endif
3146
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
B
bellard 已提交
3147
{
3148 3149 3150
    uint32_t lev;

    lev = (ctx->opcode >> 5) & 0x7F;
3151
    GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
B
bellard 已提交
3152 3153 3154 3155
}

/***                                Trap                                   ***/
/* tw */
3156
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
B
bellard 已提交
3157
{
3158 3159
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
3160
    /* Update the nip since this might generate a trap exception */
3161
    gen_update_nip(ctx, ctx->nip);
3162
    gen_op_tw(TO(ctx->opcode));
B
bellard 已提交
3163 3164 3165 3166 3167
}

/* twi */
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
3168
    gen_op_load_gpr_T0(rA(ctx->opcode));
3169 3170 3171
    gen_set_T1(SIMM(ctx->opcode));
    /* Update the nip since this might generate a trap exception */
    gen_update_nip(ctx, ctx->nip);
3172
    gen_op_tw(TO(ctx->opcode));
B
bellard 已提交
3173 3174
}

3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196
#if defined(TARGET_PPC64)
/* td */
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    /* 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)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_set_T1(SIMM(ctx->opcode));
    /* 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 已提交
3197 3198 3199 3200 3201 3202
/***                          Processor control                            ***/
/* mcrxr */
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
{
    gen_op_load_xer_cr();
    gen_op_store_T0_crf(crfD(ctx->opcode));
J
j_mayer 已提交
3203 3204
    gen_op_clear_xer_ov();
    gen_op_clear_xer_ca();
B
bellard 已提交
3205 3206 3207
}

/* mfcr */
3208
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
B
bellard 已提交
3209
{
3210
    uint32_t crm, crn;
3211

3212 3213 3214 3215 3216 3217
    if (likely(ctx->opcode & 0x00100000)) {
        crm = CRM(ctx->opcode);
        if (likely((crm ^ (crm - 1)) == 0)) {
            crn = ffs(crm);
            gen_op_load_cro(7 - crn);
        }
3218 3219 3220
    } else {
        gen_op_load_cr();
    }
B
bellard 已提交
3221 3222 3223 3224 3225 3226
    gen_op_store_T0_gpr(rD(ctx->opcode));
}

/* mfmsr */
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
{
3227
#if defined(CONFIG_USER_ONLY)
3228
    GEN_EXCP_PRIVREG(ctx);
3229
#else
3230
    if (unlikely(!ctx->supervisor)) {
3231
        GEN_EXCP_PRIVREG(ctx);
3232
        return;
3233
    }
B
bellard 已提交
3234 3235
    gen_op_load_msr();
    gen_op_store_T0_gpr(rD(ctx->opcode));
3236
#endif
B
bellard 已提交
3237 3238
}

J
j_mayer 已提交
3239
#if 1
3240
#define SPR_NOACCESS ((void *)(-1UL))
3241 3242 3243 3244 3245 3246 3247 3248 3249
#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 已提交
3250
/* mfspr */
3251
static always_inline void gen_op_mfspr (DisasContext *ctx)
B
bellard 已提交
3252
{
3253
    void (*read_cb)(void *opaque, int sprn);
B
bellard 已提交
3254 3255
    uint32_t sprn = SPR(ctx->opcode);

3256
#if !defined(CONFIG_USER_ONLY)
3257 3258
    if (ctx->supervisor == 2)
        read_cb = ctx->spr_cb[sprn].hea_read;
3259
    else if (ctx->supervisor)
3260 3261
        read_cb = ctx->spr_cb[sprn].oea_read;
    else
3262
#endif
3263
        read_cb = ctx->spr_cb[sprn].uea_read;
3264 3265
    if (likely(read_cb != NULL)) {
        if (likely(read_cb != SPR_NOACCESS)) {
3266 3267 3268 3269
            (*read_cb)(ctx, sprn);
            gen_op_store_T0_gpr(rD(ctx->opcode));
        } else {
            /* Privilege exception */
3270 3271 3272 3273 3274 3275
            /* 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) {
3276
                    fprintf(logfile, "Trying to read privileged spr %d %03x at "
J
j_mayer 已提交
3277
                            ADDRX "\n", sprn, sprn, ctx->nip);
3278
                }
J
j_mayer 已提交
3279 3280
                printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
                       sprn, sprn, ctx->nip);
3281
            }
3282
            GEN_EXCP_PRIVREG(ctx);
B
bellard 已提交
3283
        }
3284 3285
    } else {
        /* Not defined */
J
j_mayer 已提交
3286
        if (loglevel != 0) {
J
j_mayer 已提交
3287 3288
            fprintf(logfile, "Trying to read invalid spr %d %03x at "
                    ADDRX "\n", sprn, sprn, ctx->nip);
3289
        }
J
j_mayer 已提交
3290 3291
        printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
               sprn, sprn, ctx->nip);
3292 3293
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3294 3295 3296
    }
}

3297
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
B
bellard 已提交
3298
{
3299
    gen_op_mfspr(ctx);
3300
}
3301 3302

/* mftb */
3303
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3304 3305
{
    gen_op_mfspr(ctx);
B
bellard 已提交
3306 3307 3308
}

/* mtcrf */
3309
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
B
bellard 已提交
3310
{
3311
    uint32_t crm, crn;
3312

B
bellard 已提交
3313
    gen_op_load_gpr_T0(rS(ctx->opcode));
3314 3315 3316 3317 3318 3319 3320 3321 3322
    crm = CRM(ctx->opcode);
    if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
        crn = ffs(crm);
        gen_op_srli_T0(crn * 4);
        gen_op_andi_T0(0xF);
        gen_op_store_cro(7 - crn);
    } else {
        gen_op_store_cr(crm);
    }
B
bellard 已提交
3323 3324 3325
}

/* mtmsr */
J
j_mayer 已提交
3326
#if defined(TARGET_PPC64)
3327
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
J
j_mayer 已提交
3328 3329
{
#if defined(CONFIG_USER_ONLY)
3330
    GEN_EXCP_PRIVREG(ctx);
J
j_mayer 已提交
3331 3332
#else
    if (unlikely(!ctx->supervisor)) {
3333
        GEN_EXCP_PRIVREG(ctx);
J
j_mayer 已提交
3334 3335 3336
        return;
    }
    gen_op_load_gpr_T0(rS(ctx->opcode));
3337 3338 3339 3340
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
        gen_op_update_riee();
    } else {
3341 3342 3343 3344
        /* 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
         */
3345 3346 3347 3348
        gen_update_nip(ctx, ctx->nip);
        gen_op_store_msr();
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsr is not always defined as context-synchronizing */
3349
        ctx->exception = POWERPC_EXCP_STOP;
3350
    }
J
j_mayer 已提交
3351 3352 3353 3354
#endif
}
#endif

B
bellard 已提交
3355 3356
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
{
3357
#if defined(CONFIG_USER_ONLY)
3358
    GEN_EXCP_PRIVREG(ctx);
3359
#else
3360
    if (unlikely(!ctx->supervisor)) {
3361
        GEN_EXCP_PRIVREG(ctx);
3362
        return;
3363
    }
B
bellard 已提交
3364
    gen_op_load_gpr_T0(rS(ctx->opcode));
3365 3366 3367 3368
    if (ctx->opcode & 0x00010000) {
        /* Special form that does not need any synchronisation */
        gen_op_update_riee();
    } else {
3369 3370 3371 3372
        /* 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
         */
3373
        gen_update_nip(ctx, ctx->nip);
3374
#if defined(TARGET_PPC64)
3375 3376 3377
        if (!ctx->sf_mode)
            gen_op_store_msr_32();
        else
3378
#endif
3379 3380 3381
            gen_op_store_msr();
        /* Must stop the translation as machine state (may have) changed */
        /* Note that mtmsrd is not always defined as context-synchronizing */
3382
        ctx->exception = POWERPC_EXCP_STOP;
3383
    }
3384
#endif
B
bellard 已提交
3385 3386 3387 3388 3389
}

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

3393
#if !defined(CONFIG_USER_ONLY)
3394 3395
    if (ctx->supervisor == 2)
        write_cb = ctx->spr_cb[sprn].hea_write;
3396
    else if (ctx->supervisor)
3397 3398
        write_cb = ctx->spr_cb[sprn].oea_write;
    else
3399
#endif
3400
        write_cb = ctx->spr_cb[sprn].uea_write;
3401 3402
    if (likely(write_cb != NULL)) {
        if (likely(write_cb != SPR_NOACCESS)) {
3403 3404 3405 3406
            gen_op_load_gpr_T0(rS(ctx->opcode));
            (*write_cb)(ctx, sprn);
        } else {
            /* Privilege exception */
J
j_mayer 已提交
3407
            if (loglevel != 0) {
J
j_mayer 已提交
3408 3409
                fprintf(logfile, "Trying to write privileged spr %d %03x at "
                        ADDRX "\n", sprn, sprn, ctx->nip);
3410
            }
J
j_mayer 已提交
3411 3412
            printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
                   sprn, sprn, ctx->nip);
3413
            GEN_EXCP_PRIVREG(ctx);
3414
        }
3415 3416
    } else {
        /* Not defined */
J
j_mayer 已提交
3417
        if (loglevel != 0) {
J
j_mayer 已提交
3418 3419
            fprintf(logfile, "Trying to write invalid spr %d %03x at "
                    ADDRX "\n", sprn, sprn, ctx->nip);
3420
        }
J
j_mayer 已提交
3421 3422
        printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
               sprn, sprn, ctx->nip);
3423 3424
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
B
bellard 已提交
3425 3426 3427 3428 3429
    }
}

/***                         Cache management                              ***/
/* dcbf */
3430
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
B
bellard 已提交
3431
{
J
j_mayer 已提交
3432
    /* XXX: specification says this is treated as a load by the MMU */
3433
    gen_addr_reg_index(ctx);
3434
    op_ldst(lbz);
B
bellard 已提交
3435 3436 3437
}

/* dcbi (Supervisor only) */
3438
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
B
bellard 已提交
3439
{
3440
#if defined(CONFIG_USER_ONLY)
3441
    GEN_EXCP_PRIVOPC(ctx);
3442
#else
3443
    if (unlikely(!ctx->supervisor)) {
3444
        GEN_EXCP_PRIVOPC(ctx);
3445
        return;
3446
    }
3447 3448
    gen_addr_reg_index(ctx);
    /* XXX: specification says this should be treated as a store by the MMU */
J
j_mayer 已提交
3449
    op_ldst(lbz);
3450 3451
    op_ldst(stb);
#endif
B
bellard 已提交
3452 3453 3454
}

/* dcdst */
3455
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
B
bellard 已提交
3456
{
3457 3458
    /* XXX: specification say this is treated as a load by the MMU */
    gen_addr_reg_index(ctx);
3459
    op_ldst(lbz);
B
bellard 已提交
3460 3461 3462
}

/* dcbt */
3463
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
B
bellard 已提交
3464
{
3465
    /* interpreted as no-op */
3466 3467 3468
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
3469 3470 3471
}

/* dcbtst */
3472
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
B
bellard 已提交
3473
{
3474
    /* interpreted as no-op */
3475 3476 3477
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
3478 3479 3480
}

/* dcbz */
3481
#define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
3482 3483
static GenOpFunc *gen_op_dcbz[4][NB_MEM_FUNCS] = {
    /* 32 bytes cache line size */
3484
    {
3485 3486 3487 3488 3489 3490 3491 3492 3493
#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),
3494
    },
3495
    /* 64 bytes cache line size */
3496
    {
3497 3498 3499 3500 3501 3502 3503 3504 3505
#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),
3506
    },
3507
    /* 128 bytes cache line size */
3508
    {
3509 3510 3511 3512 3513 3514 3515 3516 3517
#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),
3518
    },
3519
    /* tunable cache line size */
3520
    {
3521 3522 3523 3524 3525 3526 3527 3528 3529
#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),
3530
    },
3531
};
3532

3533 3534
static always_inline void handler_dcbz (DisasContext *ctx,
                                        int dcache_line_size)
3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
{
    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 已提交
3556
{
3557
    gen_addr_reg_index(ctx);
3558 3559 3560 3561
    handler_dcbz(ctx, ctx->dcache_line_size);
    gen_op_check_reservation();
}

3562
GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
3563 3564 3565 3566 3567 3568
{
    gen_addr_reg_index(ctx);
    if (ctx->opcode & 0x00200000)
        handler_dcbz(ctx, ctx->dcache_line_size);
    else
        handler_dcbz(ctx, -1);
B
bellard 已提交
3569
    gen_op_check_reservation();
B
bellard 已提交
3570 3571 3572
}

/* icbi */
3573
#define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
3574 3575 3576 3577 3578 3579 3580 3581 3582 3583
#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),
3584
};
3585

3586
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
B
bellard 已提交
3587
{
3588 3589
    /* NIP cannot be restored if the memory exception comes from an helper */
    gen_update_nip(ctx, ctx->nip - 4);
3590
    gen_addr_reg_index(ctx);
3591
    op_icbi();
B
bellard 已提交
3592 3593 3594 3595
}

/* Optional: */
/* dcba */
3596
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
B
bellard 已提交
3597
{
3598 3599 3600 3601
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a store by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
3602 3603 3604 3605 3606 3607 3608
}

/***                    Segment register manipulation                      ***/
/* Supervisor only: */
/* mfsr */
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
{
3609
#if defined(CONFIG_USER_ONLY)
3610
    GEN_EXCP_PRIVREG(ctx);
3611
#else
3612
    if (unlikely(!ctx->supervisor)) {
3613
        GEN_EXCP_PRIVREG(ctx);
3614
        return;
3615
    }
3616 3617
    gen_op_set_T1(SR(ctx->opcode));
    gen_op_load_sr();
3618 3619
    gen_op_store_T0_gpr(rD(ctx->opcode));
#endif
B
bellard 已提交
3620 3621 3622
}

/* mfsrin */
3623
GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
B
bellard 已提交
3624
{
3625
#if defined(CONFIG_USER_ONLY)
3626
    GEN_EXCP_PRIVREG(ctx);
3627
#else
3628
    if (unlikely(!ctx->supervisor)) {
3629
        GEN_EXCP_PRIVREG(ctx);
3630
        return;
3631 3632
    }
    gen_op_load_gpr_T1(rB(ctx->opcode));
3633 3634
    gen_op_srli_T1(28);
    gen_op_load_sr();
3635 3636
    gen_op_store_T0_gpr(rD(ctx->opcode));
#endif
B
bellard 已提交
3637 3638 3639
}

/* mtsr */
B
bellard 已提交
3640
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
B
bellard 已提交
3641
{
3642
#if defined(CONFIG_USER_ONLY)
3643
    GEN_EXCP_PRIVREG(ctx);
3644
#else
3645
    if (unlikely(!ctx->supervisor)) {
3646
        GEN_EXCP_PRIVREG(ctx);
3647
        return;
3648 3649
    }
    gen_op_load_gpr_T0(rS(ctx->opcode));
3650 3651
    gen_op_set_T1(SR(ctx->opcode));
    gen_op_store_sr();
3652
#endif
B
bellard 已提交
3653 3654 3655
}

/* mtsrin */
3656
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
B
bellard 已提交
3657
{
3658
#if defined(CONFIG_USER_ONLY)
3659
    GEN_EXCP_PRIVREG(ctx);
3660
#else
3661
    if (unlikely(!ctx->supervisor)) {
3662
        GEN_EXCP_PRIVREG(ctx);
3663
        return;
3664 3665 3666
    }
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
3667 3668
    gen_op_srli_T1(28);
    gen_op_store_sr();
3669
#endif
B
bellard 已提交
3670 3671
}

3672 3673 3674
#if defined(TARGET_PPC64)
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
/* mfsr */
3675
GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
    gen_op_set_T1(SR(ctx->opcode));
    gen_op_load_slb();
    gen_op_store_T0_gpr(rD(ctx->opcode));
#endif
}

/* mfsrin */
3691 3692
GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
             PPC_SEGMENT_64B)
3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_srli_T1(28);
    gen_op_load_slb();
    gen_op_store_T0_gpr(rD(ctx->opcode));
#endif
}

/* mtsr */
3709
GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_set_T1(SR(ctx->opcode));
    gen_op_store_slb();
#endif
}

/* mtsrin */
3725 3726
GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
             PPC_SEGMENT_64B)
3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVREG(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVREG(ctx);
        return;
    }
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_srli_T1(28);
    gen_op_store_slb();
#endif
}
#endif /* defined(TARGET_PPC64) */

B
bellard 已提交
3743 3744 3745
/***                      Lookaside buffer management                      ***/
/* Optional & supervisor only: */
/* tlbia */
3746
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
B
bellard 已提交
3747
{
3748
#if defined(CONFIG_USER_ONLY)
3749
    GEN_EXCP_PRIVOPC(ctx);
3750
#else
3751
    if (unlikely(!ctx->supervisor)) {
3752
        GEN_EXCP_PRIVOPC(ctx);
3753
        return;
3754 3755 3756
    }
    gen_op_tlbia();
#endif
B
bellard 已提交
3757 3758 3759
}

/* tlbie */
3760
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
B
bellard 已提交
3761
{
3762
#if defined(CONFIG_USER_ONLY)
3763
    GEN_EXCP_PRIVOPC(ctx);
3764
#else
3765
    if (unlikely(!ctx->supervisor)) {
3766
        GEN_EXCP_PRIVOPC(ctx);
3767
        return;
3768 3769
    }
    gen_op_load_gpr_T0(rB(ctx->opcode));
3770 3771 3772 3773 3774 3775
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_tlbie_64();
    else
#endif
        gen_op_tlbie();
3776
#endif
B
bellard 已提交
3777 3778 3779
}

/* tlbsync */
3780
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
B
bellard 已提交
3781
{
3782
#if defined(CONFIG_USER_ONLY)
3783
    GEN_EXCP_PRIVOPC(ctx);
3784
#else
3785
    if (unlikely(!ctx->supervisor)) {
3786
        GEN_EXCP_PRIVOPC(ctx);
3787
        return;
3788 3789 3790 3791
    }
    /* This has no effect: it should ensure that all previous
     * tlbie have completed
     */
3792
    GEN_STOP(ctx);
3793
#endif
B
bellard 已提交
3794 3795
}

J
j_mayer 已提交
3796 3797 3798 3799 3800
#if defined(TARGET_PPC64)
/* slbia */
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
{
#if defined(CONFIG_USER_ONLY)
3801
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3802 3803
#else
    if (unlikely(!ctx->supervisor)) {
3804
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3805 3806 3807 3808 3809 3810 3811 3812 3813 3814
        return;
    }
    gen_op_slbia();
#endif
}

/* slbie */
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
{
#if defined(CONFIG_USER_ONLY)
3815
    GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3816 3817
#else
    if (unlikely(!ctx->supervisor)) {
3818
        GEN_EXCP_PRIVOPC(ctx);
J
j_mayer 已提交
3819 3820 3821 3822 3823 3824 3825 3826
        return;
    }
    gen_op_load_gpr_T0(rB(ctx->opcode));
    gen_op_slbie();
#endif
}
#endif

B
bellard 已提交
3827 3828
/***                              External control                         ***/
/* Optional: */
3829 3830
#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
3831 3832
static GenOpFunc *gen_op_eciwx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(eciwx),
3833
};
3834 3835
static GenOpFunc *gen_op_ecowx[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(ecowx),
3836
};
3837

3838
/* eciwx */
B
bellard 已提交
3839 3840
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
{
3841
    /* Should check EAR[E] & alignment ! */
3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877
    gen_addr_reg_index(ctx);
    op_eciwx();
    gen_op_store_T0_gpr(rD(ctx->opcode));
}

/* ecowx */
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
{
    /* Should check EAR[E] & alignment ! */
    gen_addr_reg_index(ctx);
    gen_op_load_gpr_T1(rS(ctx->opcode));
    op_ecowx();
}

/* PowerPC 601 specific instructions */
/* abs - abs. */
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_POWER_abs();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* abso - abso. */
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_POWER_abso();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* clcs */
3878
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
3879 3880 3881
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_POWER_clcs();
3882
    /* Rc=1 sets CR0 to an undefined state */
3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960
    gen_op_store_T0_gpr(rD(ctx->opcode));
}

/* div - div. */
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_div();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* divo - divo. */
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_divo();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* divs - divs. */
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_divs();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* divso - divso. */
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_divso();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* doz - doz. */
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_doz();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* dozo - dozo. */
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_dozo();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* dozi */
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_set_T1(SIMM(ctx->opcode));
    gen_op_POWER_doz();
    gen_op_store_T0_gpr(rD(ctx->opcode));
}

3961 3962 3963
/* 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
 */
3964
#define op_POWER_lscbx(start, ra, rb)                                         \
3965
(*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979
#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),
3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992
};

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

    gen_addr_reg_index(ctx);
    if (ra == 0) {
        ra = rb;
    }
    /* NIP cannot be restored if the memory exception comes from an helper */
3993
    gen_update_nip(ctx, ctx->nip - 4);
3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160
    gen_op_load_xer_bc();
    gen_op_load_xer_cmp();
    op_POWER_lscbx(rD(ctx->opcode), ra, rb);
    gen_op_store_xer_bc();
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* maskg - maskg. */
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_maskg();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* maskir - maskir. */
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rS(ctx->opcode));
    gen_op_load_gpr_T2(rB(ctx->opcode));
    gen_op_POWER_maskir();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* mul - mul. */
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_mul();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* mulo - mulo. */
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_mulo();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* nabs - nabs. */
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_POWER_nabs();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* nabso - nabso. */
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_POWER_nabso();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

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

    mb = MB(ctx->opcode);
    me = ME(ctx->opcode);
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rA(ctx->opcode));
    gen_op_load_gpr_T2(rB(ctx->opcode));
    gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* rrib - rrib. */
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rA(ctx->opcode));
    gen_op_load_gpr_T2(rB(ctx->opcode));
    gen_op_POWER_rrib();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sle - sle. */
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_sle();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sleq - sleq. */
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_sleq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sliq - sliq. */
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_set_T1(SH(ctx->opcode));
    gen_op_POWER_sle();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* slliq - slliq. */
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_set_T1(SH(ctx->opcode));
    gen_op_POWER_sleq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sllq - sllq. */
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_sllq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* slq - slq. */
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_slq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

4161
/* sraiq - sraiq. */
4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_set_T1(SH(ctx->opcode));
    gen_op_POWER_sraq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sraq - sraq. */
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_sraq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sre - sre. */
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_sre();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* srea - srea. */
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_srea();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sreq */
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_sreq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* sriq */
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_set_T1(SH(ctx->opcode));
    gen_op_POWER_srq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* srliq */
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_set_T1(SH(ctx->opcode));
    gen_op_POWER_srlq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* srlq */
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_srlq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* srq */
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_POWER_srq();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    if (unlikely(Rc(ctx->opcode) != 0))
        gen_set_Rc0(ctx);
}

/* PowerPC 602 specific instructions */
/* dsa  */
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4266
    GEN_EXCP_INVAL(ctx);
4267 4268 4269 4270 4271 4272
}

/* esa */
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
{
    /* XXX: TODO */
4273
    GEN_EXCP_INVAL(ctx);
4274 4275 4276 4277 4278 4279
}

/* mfrom */
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
{
#if defined(CONFIG_USER_ONLY)
4280
    GEN_EXCP_PRIVOPC(ctx);
4281 4282
#else
    if (unlikely(!ctx->supervisor)) {
4283
        GEN_EXCP_PRIVOPC(ctx);
4284 4285 4286 4287 4288 4289 4290 4291 4292 4293
        return;
    }
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_602_mfrom();
    gen_op_store_T0_gpr(rD(ctx->opcode));
#endif
}

/* 602 - 603 - G2 TLB management */
/* tlbld */
4294
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
4295 4296
{
#if defined(CONFIG_USER_ONLY)
4297
    GEN_EXCP_PRIVOPC(ctx);
4298 4299
#else
    if (unlikely(!ctx->supervisor)) {
4300
        GEN_EXCP_PRIVOPC(ctx);
4301 4302 4303 4304 4305 4306 4307 4308
        return;
    }
    gen_op_load_gpr_T0(rB(ctx->opcode));
    gen_op_6xx_tlbld();
#endif
}

/* tlbli */
4309
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
4310 4311
{
#if defined(CONFIG_USER_ONLY)
4312
    GEN_EXCP_PRIVOPC(ctx);
4313 4314
#else
    if (unlikely(!ctx->supervisor)) {
4315
        GEN_EXCP_PRIVOPC(ctx);
4316 4317 4318 4319 4320 4321 4322
        return;
    }
    gen_op_load_gpr_T0(rB(ctx->opcode));
    gen_op_6xx_tlbli();
#endif
}

4323 4324
/* 74xx TLB management */
/* tlbld */
4325
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
    gen_op_load_gpr_T0(rB(ctx->opcode));
    gen_op_74xx_tlbld();
#endif
}

/* tlbli */
4340
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353
{
#if defined(CONFIG_USER_ONLY)
    GEN_EXCP_PRIVOPC(ctx);
#else
    if (unlikely(!ctx->supervisor)) {
        GEN_EXCP_PRIVOPC(ctx);
        return;
    }
    gen_op_load_gpr_T0(rB(ctx->opcode));
    gen_op_74xx_tlbli();
#endif
}

4354 4355 4356 4357 4358 4359 4360 4361 4362 4363
/* 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 已提交
4364
    /* Cache line invalidate: privileged and treated as no-op */
4365
#if defined(CONFIG_USER_ONLY)
4366
    GEN_EXCP_PRIVOPC(ctx);
4367 4368
#else
    if (unlikely(!ctx->supervisor)) {
4369
        GEN_EXCP_PRIVOPC(ctx);
4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383
        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)
4384
    GEN_EXCP_PRIVOPC(ctx);
4385 4386
#else
    if (unlikely(!ctx->supervisor)) {
4387
        GEN_EXCP_PRIVOPC(ctx);
4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403
        return;
    }
    int ra = rA(ctx->opcode);
    int rd = rD(ctx->opcode);

    gen_addr_reg_index(ctx);
    gen_op_POWER_mfsri();
    gen_op_store_T0_gpr(rd);
    if (ra != 0 && ra != rd)
        gen_op_store_T1_gpr(ra);
#endif
}

GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
4404
    GEN_EXCP_PRIVOPC(ctx);
4405 4406
#else
    if (unlikely(!ctx->supervisor)) {
4407
        GEN_EXCP_PRIVOPC(ctx);
4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418
        return;
    }
    gen_addr_reg_index(ctx);
    gen_op_POWER_rac();
    gen_op_store_T0_gpr(rD(ctx->opcode));
#endif
}

GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
{
#if defined(CONFIG_USER_ONLY)
4419
    GEN_EXCP_PRIVOPC(ctx);
4420 4421
#else
    if (unlikely(!ctx->supervisor)) {
4422
        GEN_EXCP_PRIVOPC(ctx);
4423 4424 4425
        return;
    }
    gen_op_POWER_rfsvc();
4426
    GEN_SYNC(ctx);
4427 4428 4429 4430 4431 4432 4433
#endif
}

/* svc is not implemented for now */

/* POWER2 specific instructions */
/* Quad manipulation (load/store two floats at a time) */
4434
/* Original POWER2 is 32 bits only, define 64 bits ops as 32 bits ones */
4435 4436
#define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
#define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454
#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),
4455
};
4456 4457
static GenOpFunc *gen_op_POWER2_stfq[NB_MEM_FUNCS] = {
    GEN_MEM_FUNCS(POWER2_stfq),
4458 4459 4460 4461 4462 4463
};

/* lfq */
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
4464
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
4465
    gen_addr_imm_index(ctx, 0);
4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476
    op_POWER2_lfq();
    gen_op_store_FT0_fpr(rD(ctx->opcode));
    gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
}

/* 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 */
4477
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
4478
    gen_addr_imm_index(ctx, 0);
4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491
    op_POWER2_lfq();
    gen_op_store_FT0_fpr(rD(ctx->opcode));
    gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
    if (ra != 0)
        gen_op_store_T0_gpr(ra);
}

/* 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 */
4492
    gen_update_nip(ctx, ctx->nip - 4);
4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504
    gen_addr_reg_index(ctx);
    op_POWER2_lfq();
    gen_op_store_FT0_fpr(rD(ctx->opcode));
    gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
    if (ra != 0)
        gen_op_store_T0_gpr(ra);
}

/* lfqx */
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
4505
    gen_update_nip(ctx, ctx->nip - 4);
4506 4507 4508 4509 4510 4511 4512 4513 4514 4515
    gen_addr_reg_index(ctx);
    op_POWER2_lfq();
    gen_op_store_FT0_fpr(rD(ctx->opcode));
    gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
}

/* stfq */
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
4516
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
4517
    gen_addr_imm_index(ctx, 0);
4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528
    gen_op_load_fpr_FT0(rS(ctx->opcode));
    gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
    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 */
4529
    gen_update_nip(ctx, ctx->nip - 4);
J
j_mayer 已提交
4530
    gen_addr_imm_index(ctx, 0);
4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543
    gen_op_load_fpr_FT0(rS(ctx->opcode));
    gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
    op_POWER2_stfq();
    if (ra != 0)
        gen_op_store_T0_gpr(ra);
}

/* 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 */
4544
    gen_update_nip(ctx, ctx->nip - 4);
4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556
    gen_addr_reg_index(ctx);
    gen_op_load_fpr_FT0(rS(ctx->opcode));
    gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
    op_POWER2_stfq();
    if (ra != 0)
        gen_op_store_T0_gpr(ra);
}

/* stfqx */
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
{
    /* NIP cannot be restored if the memory exception comes from an helper */
4557
    gen_update_nip(ctx, ctx->nip - 4);
4558 4559 4560 4561 4562 4563 4564
    gen_addr_reg_index(ctx);
    gen_op_load_fpr_FT0(rS(ctx->opcode));
    gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
    op_POWER2_stfq();
}

/* BookE specific instructions */
4565
/* XXX: not implemented on 440 ? */
4566
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
4567 4568
{
    /* XXX: TODO */
4569
    GEN_EXCP_INVAL(ctx);
4570 4571
}

4572
/* XXX: not implemented on 440 ? */
4573
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
4574 4575
{
#if defined(CONFIG_USER_ONLY)
4576
    GEN_EXCP_PRIVOPC(ctx);
4577 4578
#else
    if (unlikely(!ctx->supervisor)) {
4579
        GEN_EXCP_PRIVOPC(ctx);
4580 4581 4582 4583
        return;
    }
    gen_addr_reg_index(ctx);
    /* Use the same micro-ops as for tlbie */
4584 4585 4586 4587 4588 4589
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
        gen_op_tlbie_64();
    else
#endif
        gen_op_tlbie();
4590 4591 4592 4593
#endif
}

/* All 405 MAC instructions are translated here */
4594 4595 4596
static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
                                                int opc2, int opc3,
                                                int ra, int rb, int rt, int Rc)
4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656
{
    gen_op_load_gpr_T0(ra);
    gen_op_load_gpr_T1(rb);
    switch (opc3 & 0x0D) {
    case 0x05:
        /* macchw    - macchw.    - macchwo   - macchwo.   */
        /* macchws   - macchws.   - macchwso  - macchwso.  */
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
        /* mulchw - mulchw. */
        gen_op_405_mulchw();
        break;
    case 0x04:
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
        /* mulchwu - mulchwu. */
        gen_op_405_mulchwu();
        break;
    case 0x01:
        /* machhw    - machhw.    - machhwo   - machhwo.   */
        /* machhws   - machhws.   - machhwso  - machhwso.  */
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
        /* mulhhw - mulhhw. */
        gen_op_405_mulhhw();
        break;
    case 0x00:
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
        /* mulhhwu - mulhhwu. */
        gen_op_405_mulhhwu();
        break;
    case 0x0D:
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
        /* mullhw - mullhw. */
        gen_op_405_mullhw();
        break;
    case 0x0C:
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
        /* mullhwu - mullhwu. */
        gen_op_405_mullhwu();
        break;
    }
    if (opc2 & 0x02) {
        /* nmultiply-and-accumulate (0x0E) */
        gen_op_neg();
    }
    if (opc2 & 0x04) {
        /* (n)multiply-and-accumulate (0x0C - 0x0E) */
        gen_op_load_gpr_T2(rt);
        gen_op_move_T1_T0();
        gen_op_405_add_T0_T2();
    }
    if (opc3 & 0x10) {
        /* Check overflow */
        if (opc3 & 0x01)
4657
            gen_op_check_addo();
4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674
        else
            gen_op_405_check_ovu();
    }
    if (opc3 & 0x02) {
        /* Saturate */
        if (opc3 & 0x01)
            gen_op_405_check_sat();
        else
            gen_op_405_check_satu();
    }
    gen_op_store_T0_gpr(rt);
    if (unlikely(Rc) != 0) {
        /* Update Rc0 */
        gen_set_Rc0(ctx);
    }
}

4675 4676
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)                  \
4677 4678 4679 4680 4681 4682
{                                                                             \
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
}

/* macchw    - macchw.    */
4683
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
4684
/* macchwo   - macchwo.   */
4685
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
4686
/* macchws   - macchws.   */
4687
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
4688
/* macchwso  - macchwso.  */
4689
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
4690
/* macchwsu  - macchwsu.  */
4691
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
4692
/* macchwsuo - macchwsuo. */
4693
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
4694
/* macchwu   - macchwu.   */
4695
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
4696
/* macchwuo  - macchwuo.  */
4697
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
4698
/* machhw    - machhw.    */
4699
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
4700
/* machhwo   - machhwo.   */
4701
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
4702
/* machhws   - machhws.   */
4703
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
4704
/* machhwso  - machhwso.  */
4705
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
4706
/* machhwsu  - machhwsu.  */
4707
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
4708
/* machhwsuo - machhwsuo. */
4709
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
4710
/* machhwu   - machhwu.   */
4711
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
4712
/* machhwuo  - machhwuo.  */
4713
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
4714
/* maclhw    - maclhw.    */
4715
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
4716
/* maclhwo   - maclhwo.   */
4717
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
4718
/* maclhws   - maclhws.   */
4719
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
4720
/* maclhwso  - maclhwso.  */
4721
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
4722
/* maclhwu   - maclhwu.   */
4723
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
4724
/* maclhwuo  - maclhwuo.  */
4725
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
4726
/* maclhwsu  - maclhwsu.  */
4727
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
4728
/* maclhwsuo - maclhwsuo. */
4729
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
4730
/* nmacchw   - nmacchw.   */
4731
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
4732
/* nmacchwo  - nmacchwo.  */
4733
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
4734
/* nmacchws  - nmacchws.  */
4735
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
4736
/* nmacchwso - nmacchwso. */
4737
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
4738
/* nmachhw   - nmachhw.   */
4739
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
4740
/* nmachhwo  - nmachhwo.  */
4741
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
4742
/* nmachhws  - nmachhws.  */
4743
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
4744
/* nmachhwso - nmachhwso. */
4745
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
4746
/* nmaclhw   - nmaclhw.   */
4747
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
4748
/* nmaclhwo  - nmaclhwo.  */
4749
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
4750
/* nmaclhws  - nmaclhws.  */
4751
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
4752
/* nmaclhwso - nmaclhwso. */
4753
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
4754 4755

/* mulchw  - mulchw.  */
4756
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
4757
/* mulchwu - mulchwu. */
4758
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
4759
/* mulhhw  - mulhhw.  */
4760
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
4761
/* mulhhwu - mulhhwu. */
4762
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
4763
/* mullhw  - mullhw.  */
4764
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
4765
/* mullhwu - mullhwu. */
4766
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
4767 4768

/* mfdcr */
4769
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
4770 4771
{
#if defined(CONFIG_USER_ONLY)
4772
    GEN_EXCP_PRIVREG(ctx);
4773 4774 4775 4776
#else
    uint32_t dcrn = SPR(ctx->opcode);

    if (unlikely(!ctx->supervisor)) {
4777
        GEN_EXCP_PRIVREG(ctx);
4778 4779
        return;
    }
4780 4781
    gen_op_set_T0(dcrn);
    gen_op_load_dcr();
4782 4783 4784 4785 4786
    gen_op_store_T0_gpr(rD(ctx->opcode));
#endif
}

/* mtdcr */
4787
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
4788 4789
{
#if defined(CONFIG_USER_ONLY)
4790
    GEN_EXCP_PRIVREG(ctx);
4791 4792 4793 4794
#else
    uint32_t dcrn = SPR(ctx->opcode);

    if (unlikely(!ctx->supervisor)) {
4795
        GEN_EXCP_PRIVREG(ctx);
4796 4797
        return;
    }
4798 4799 4800 4801 4802 4803 4804
    gen_op_set_T0(dcrn);
    gen_op_load_gpr_T1(rS(ctx->opcode));
    gen_op_store_dcr();
#endif
}

/* mfdcrx */
4805
/* XXX: not implemented on 440 ? */
4806
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
4807 4808
{
#if defined(CONFIG_USER_ONLY)
4809
    GEN_EXCP_PRIVREG(ctx);
4810 4811
#else
    if (unlikely(!ctx->supervisor)) {
4812
        GEN_EXCP_PRIVREG(ctx);
4813 4814 4815 4816 4817
        return;
    }
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_dcr();
    gen_op_store_T0_gpr(rD(ctx->opcode));
4818
    /* Note: Rc update flag set leads to undefined state of Rc0 */
4819 4820 4821 4822
#endif
}

/* mtdcrx */
4823
/* XXX: not implemented on 440 ? */
4824
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
4825 4826
{
#if defined(CONFIG_USER_ONLY)
4827
    GEN_EXCP_PRIVREG(ctx);
4828 4829
#else
    if (unlikely(!ctx->supervisor)) {
4830
        GEN_EXCP_PRIVREG(ctx);
4831 4832 4833 4834 4835
        return;
    }
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rS(ctx->opcode));
    gen_op_store_dcr();
4836
    /* Note: Rc update flag set leads to undefined state of Rc0 */
4837 4838 4839
#endif
}

4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857
/* mfdcrux (PPC 460) : user-mode access to DCR */
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_dcr();
    gen_op_store_T0_gpr(rD(ctx->opcode));
    /* 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)
{
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rS(ctx->opcode));
    gen_op_store_dcr();
    /* Note: Rc update flag set leads to undefined state of Rc0 */
}

4858 4859 4860 4861
/* dccci */
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
4862
    GEN_EXCP_PRIVOPC(ctx);
4863 4864
#else
    if (unlikely(!ctx->supervisor)) {
4865
        GEN_EXCP_PRIVOPC(ctx);
4866 4867 4868 4869 4870 4871 4872 4873 4874 4875
        return;
    }
    /* interpreted as no-op */
#endif
}

/* dcread */
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
{
#if defined(CONFIG_USER_ONLY)
4876
    GEN_EXCP_PRIVOPC(ctx);
4877 4878
#else
    if (unlikely(!ctx->supervisor)) {
4879
        GEN_EXCP_PRIVOPC(ctx);
4880 4881 4882 4883 4884 4885 4886 4887 4888
        return;
    }
    gen_addr_reg_index(ctx);
    op_ldst(lwz);
    gen_op_store_T0_gpr(rD(ctx->opcode));
#endif
}

/* icbt */
4889
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900
{
    /* 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)
4901
    GEN_EXCP_PRIVOPC(ctx);
4902 4903
#else
    if (unlikely(!ctx->supervisor)) {
4904
        GEN_EXCP_PRIVOPC(ctx);
4905 4906 4907 4908 4909 4910 4911 4912 4913 4914
        return;
    }
    /* interpreted as no-op */
#endif
}

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

/* rfci (supervisor only) */
4926
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
4927 4928
{
#if defined(CONFIG_USER_ONLY)
4929
    GEN_EXCP_PRIVOPC(ctx);
4930 4931
#else
    if (unlikely(!ctx->supervisor)) {
4932
        GEN_EXCP_PRIVOPC(ctx);
4933 4934 4935 4936
        return;
    }
    /* Restore CPU state */
    gen_op_40x_rfci();
4937
    GEN_SYNC(ctx);
4938 4939 4940 4941 4942 4943
#endif
}

GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
{
#if defined(CONFIG_USER_ONLY)
4944
    GEN_EXCP_PRIVOPC(ctx);
4945 4946
#else
    if (unlikely(!ctx->supervisor)) {
4947
        GEN_EXCP_PRIVOPC(ctx);
4948 4949 4950 4951
        return;
    }
    /* Restore CPU state */
    gen_op_rfci();
4952
    GEN_SYNC(ctx);
4953 4954 4955 4956
#endif
}

/* BookE specific */
4957
/* XXX: not implemented on 440 ? */
4958
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
4959 4960
{
#if defined(CONFIG_USER_ONLY)
4961
    GEN_EXCP_PRIVOPC(ctx);
4962 4963
#else
    if (unlikely(!ctx->supervisor)) {
4964
        GEN_EXCP_PRIVOPC(ctx);
4965 4966 4967
        return;
    }
    /* Restore CPU state */
4968
    gen_op_rfdi();
4969
    GEN_SYNC(ctx);
4970 4971 4972
#endif
}

4973
/* XXX: not implemented on 440 ? */
4974
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
4975 4976
{
#if defined(CONFIG_USER_ONLY)
4977
    GEN_EXCP_PRIVOPC(ctx);
4978 4979
#else
    if (unlikely(!ctx->supervisor)) {
4980
        GEN_EXCP_PRIVOPC(ctx);
4981 4982 4983 4984
        return;
    }
    /* Restore CPU state */
    gen_op_rfmci();
4985
    GEN_SYNC(ctx);
4986 4987
#endif
}
4988

4989
/* TLB management - PowerPC 405 implementation */
4990
/* tlbre */
4991
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
4992 4993
{
#if defined(CONFIG_USER_ONLY)
4994
    GEN_EXCP_PRIVOPC(ctx);
4995 4996
#else
    if (unlikely(!ctx->supervisor)) {
4997
        GEN_EXCP_PRIVOPC(ctx);
4998 4999 5000 5001
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5002
        gen_op_load_gpr_T0(rA(ctx->opcode));
5003 5004 5005 5006 5007 5008 5009 5010 5011
        gen_op_4xx_tlbre_hi();
        gen_op_store_T0_gpr(rD(ctx->opcode));
        break;
    case 1:
        gen_op_load_gpr_T0(rA(ctx->opcode));
        gen_op_4xx_tlbre_lo();
        gen_op_store_T0_gpr(rD(ctx->opcode));
        break;
    default:
5012
        GEN_EXCP_INVAL(ctx);
5013
        break;
5014
    }
5015 5016 5017
#endif
}

5018
/* tlbsx - tlbsx. */
5019
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5020 5021
{
#if defined(CONFIG_USER_ONLY)
5022
    GEN_EXCP_PRIVOPC(ctx);
5023 5024
#else
    if (unlikely(!ctx->supervisor)) {
5025
        GEN_EXCP_PRIVOPC(ctx);
5026 5027 5028
        return;
    }
    gen_addr_reg_index(ctx);
5029
    gen_op_4xx_tlbsx();
5030
    if (Rc(ctx->opcode))
5031
        gen_op_4xx_tlbsx_check();
5032
    gen_op_store_T0_gpr(rD(ctx->opcode));
5033
#endif
B
bellard 已提交
5034 5035
}

5036
/* tlbwe */
5037
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
B
bellard 已提交
5038
{
5039
#if defined(CONFIG_USER_ONLY)
5040
    GEN_EXCP_PRIVOPC(ctx);
5041 5042
#else
    if (unlikely(!ctx->supervisor)) {
5043
        GEN_EXCP_PRIVOPC(ctx);
5044 5045 5046 5047
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
5048
        gen_op_load_gpr_T0(rA(ctx->opcode));
5049 5050 5051 5052 5053 5054 5055 5056 5057
        gen_op_load_gpr_T1(rS(ctx->opcode));
        gen_op_4xx_tlbwe_hi();
        break;
    case 1:
        gen_op_load_gpr_T0(rA(ctx->opcode));
        gen_op_load_gpr_T1(rS(ctx->opcode));
        gen_op_4xx_tlbwe_lo();
        break;
    default:
5058
        GEN_EXCP_INVAL(ctx);
5059
        break;
5060
    }
5061 5062 5063
#endif
}

5064
/* TLB management - PowerPC 440 implementation */
5065
/* tlbre */
5066
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5067 5068
{
#if defined(CONFIG_USER_ONLY)
5069
    GEN_EXCP_PRIVOPC(ctx);
5070 5071
#else
    if (unlikely(!ctx->supervisor)) {
5072
        GEN_EXCP_PRIVOPC(ctx);
5073 5074 5075 5076 5077 5078 5079
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
        gen_op_load_gpr_T0(rA(ctx->opcode));
5080
        gen_op_440_tlbre(rB(ctx->opcode));
5081 5082 5083
        gen_op_store_T0_gpr(rD(ctx->opcode));
        break;
    default:
5084
        GEN_EXCP_INVAL(ctx);
5085 5086 5087 5088 5089 5090
        break;
    }
#endif
}

/* tlbsx - tlbsx. */
5091
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5092 5093
{
#if defined(CONFIG_USER_ONLY)
5094
    GEN_EXCP_PRIVOPC(ctx);
5095 5096
#else
    if (unlikely(!ctx->supervisor)) {
5097
        GEN_EXCP_PRIVOPC(ctx);
5098 5099 5100
        return;
    }
    gen_addr_reg_index(ctx);
5101
    gen_op_440_tlbsx();
5102
    if (Rc(ctx->opcode))
5103
        gen_op_4xx_tlbsx_check();
5104 5105 5106 5107 5108
    gen_op_store_T0_gpr(rD(ctx->opcode));
#endif
}

/* tlbwe */
5109
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5110 5111
{
#if defined(CONFIG_USER_ONLY)
5112
    GEN_EXCP_PRIVOPC(ctx);
5113 5114
#else
    if (unlikely(!ctx->supervisor)) {
5115
        GEN_EXCP_PRIVOPC(ctx);
5116 5117 5118 5119 5120 5121 5122 5123
        return;
    }
    switch (rB(ctx->opcode)) {
    case 0:
    case 1:
    case 2:
        gen_op_load_gpr_T0(rA(ctx->opcode));
        gen_op_load_gpr_T1(rS(ctx->opcode));
5124
        gen_op_440_tlbwe(rB(ctx->opcode));
5125 5126
        break;
    default:
5127
        GEN_EXCP_INVAL(ctx);
5128 5129 5130 5131 5132
        break;
    }
#endif
}

5133
/* wrtee */
5134
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
5135 5136
{
#if defined(CONFIG_USER_ONLY)
5137
    GEN_EXCP_PRIVOPC(ctx);
5138 5139
#else
    if (unlikely(!ctx->supervisor)) {
5140
        GEN_EXCP_PRIVOPC(ctx);
5141 5142 5143
        return;
    }
    gen_op_load_gpr_T0(rD(ctx->opcode));
5144
    gen_op_wrte();
J
j_mayer 已提交
5145 5146 5147
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
5148
    GEN_STOP(ctx);
5149 5150 5151 5152
#endif
}

/* wrteei */
5153
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
5154 5155
{
#if defined(CONFIG_USER_ONLY)
5156
    GEN_EXCP_PRIVOPC(ctx);
5157 5158
#else
    if (unlikely(!ctx->supervisor)) {
5159
        GEN_EXCP_PRIVOPC(ctx);
5160 5161 5162
        return;
    }
    gen_op_set_T0(ctx->opcode & 0x00010000);
5163
    gen_op_wrte();
J
j_mayer 已提交
5164 5165 5166
    /* Stop translation to have a chance to raise an exception
     * if we just set msr_ee to 1
     */
5167
    GEN_STOP(ctx);
5168 5169 5170
#endif
}

J
j_mayer 已提交
5171
/* PowerPC 440 specific instructions */
5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192
/* dlmzb */
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
{
    gen_op_load_gpr_T0(rS(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
    gen_op_440_dlmzb();
    gen_op_store_T0_gpr(rA(ctx->opcode));
    gen_op_store_xer_bc();
    if (Rc(ctx->opcode)) {
        gen_op_440_dlmzb_update_Rc();
        gen_op_store_T0_crf(0);
    }
}

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

/* msync replaces sync on 440 */
5193
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
5194 5195 5196 5197 5198
{
    /* interpreted as no-op */
}

/* icbt */
5199
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
5200 5201 5202 5203 5204
{
    /* interpreted as no-op */
    /* XXX: specification say this is treated as a load by the MMU
     *      but does not generate any exception
     */
B
bellard 已提交
5205 5206
}

5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220
/***                      Altivec vector extension                         ***/
/* Altivec registers moves */
GEN32(gen_op_load_avr_A0, gen_op_load_avr_A0_avr);
GEN32(gen_op_load_avr_A1, gen_op_load_avr_A1_avr);
GEN32(gen_op_load_avr_A2, gen_op_load_avr_A2_avr);

GEN32(gen_op_store_A0_avr, gen_op_store_A0_avr_avr);
GEN32(gen_op_store_A1_avr, gen_op_store_A1_avr_avr);
#if 0 // unused
GEN32(gen_op_store_A2_avr, gen_op_store_A2_avr_avr);
#endif

#define op_vr_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_VR_LD_TABLE(name)                                                  \
5221 5222
static GenOpFunc *gen_op_vr_l##name[NB_MEM_FUNCS] = {                         \
    GEN_MEM_FUNCS(vr_l##name),                                                \
5223 5224
};
#define OP_VR_ST_TABLE(name)                                                  \
5225 5226
static GenOpFunc *gen_op_vr_st##name[NB_MEM_FUNCS] = {                        \
    GEN_MEM_FUNCS(vr_st##name),                                               \
5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264
};

#define GEN_VR_LDX(name, opc2, opc3)                                          \
GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)               \
{                                                                             \
    if (unlikely(!ctx->altivec_enabled)) {                                    \
        GEN_EXCP_NO_VR(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    gen_addr_reg_index(ctx);                                                  \
    op_vr_ldst(vr_l##name);                                                   \
    gen_op_store_A0_avr(rD(ctx->opcode));                                     \
}

#define GEN_VR_STX(name, opc2, opc3)                                          \
GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)              \
{                                                                             \
    if (unlikely(!ctx->altivec_enabled)) {                                    \
        GEN_EXCP_NO_VR(ctx);                                                  \
        return;                                                               \
    }                                                                         \
    gen_addr_reg_index(ctx);                                                  \
    gen_op_load_avr_A0(rS(ctx->opcode));                                      \
    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);

5265 5266
/***                           SPE extension                               ***/
/* Register moves */
5267
#if !defined(TARGET_PPC64)
5268

5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280
GEN32(gen_op_load_gpr64_T0, gen_op_load_gpr64_T0_gpr);
GEN32(gen_op_load_gpr64_T1, gen_op_load_gpr64_T1_gpr);
#if 0 // unused
GEN32(gen_op_load_gpr64_T2, gen_op_load_gpr64_T2_gpr);
#endif

GEN32(gen_op_store_T0_gpr64, gen_op_store_T0_gpr64_gpr);
GEN32(gen_op_store_T1_gpr64, gen_op_store_T1_gpr64_gpr);
#if 0 // unused
GEN32(gen_op_store_T2_gpr64, gen_op_store_T2_gpr64_gpr);
#endif

5281
#else /* !defined(TARGET_PPC64) */
5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295

/* No specific load/store functions: GPRs are already 64 bits */
#define gen_op_load_gpr64_T0 gen_op_load_gpr_T0
#define gen_op_load_gpr64_T1 gen_op_load_gpr_T1
#if 0 // unused
#define gen_op_load_gpr64_T2 gen_op_load_gpr_T2
#endif

#define gen_op_store_T0_gpr64 gen_op_store_T0_gpr
#define gen_op_store_T1_gpr64 gen_op_store_T1_gpr
#if 0 // unused
#define gen_op_store_T2_gpr64 gen_op_store_T2_gpr
#endif

5296
#endif /* !defined(TARGET_PPC64) */
5297

5298 5299 5300 5301 5302 5303 5304 5305 5306 5307
#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 */
5308
static always_inline void gen_speundef (DisasContext *ctx)
5309
{
5310
    GEN_EXCP_INVAL(ctx);
5311 5312 5313
}

/* SPE load and stores */
5314
static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328
{
    target_long simm = rB(ctx->opcode);

    if (rA(ctx->opcode) == 0) {
        gen_set_T0(simm << sh);
    } else {
        gen_op_load_gpr_T0(rA(ctx->opcode));
        if (likely(simm != 0))
            gen_op_addi(simm << sh);
    }
}

#define op_spe_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
#define OP_SPE_LD_TABLE(name)                                                 \
5329 5330
static GenOpFunc *gen_op_spe_l##name[NB_MEM_FUNCS] = {                        \
    GEN_MEM_FUNCS(spe_l##name),                                               \
5331 5332
};
#define OP_SPE_ST_TABLE(name)                                                 \
5333 5334
static GenOpFunc *gen_op_spe_st##name[NB_MEM_FUNCS] = {                       \
    GEN_MEM_FUNCS(spe_st##name),                                              \
5335
};
5336 5337

#define GEN_SPE_LD(name, sh)                                                  \
5338
static always_inline void gen_evl##name (DisasContext *ctx)                   \
5339 5340
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5341
        GEN_EXCP_NO_AP(ctx);                                                  \
5342 5343 5344 5345 5346 5347 5348 5349
        return;                                                               \
    }                                                                         \
    gen_addr_spe_imm_index(ctx, sh);                                          \
    op_spe_ldst(spe_l##name);                                                 \
    gen_op_store_T1_gpr64(rD(ctx->opcode));                                   \
}

#define GEN_SPE_LDX(name)                                                     \
5350
static always_inline void gen_evl##name##x (DisasContext *ctx)                \
5351 5352
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5353
        GEN_EXCP_NO_AP(ctx);                                                  \
5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366
        return;                                                               \
    }                                                                         \
    gen_addr_reg_index(ctx);                                                  \
    op_spe_ldst(spe_l##name);                                                 \
    gen_op_store_T1_gpr64(rD(ctx->opcode));                                   \
}

#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)                                                  \
5367
static always_inline void gen_evst##name (DisasContext *ctx)                  \
5368 5369
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5370
        GEN_EXCP_NO_AP(ctx);                                                  \
5371 5372 5373 5374 5375 5376 5377 5378
        return;                                                               \
    }                                                                         \
    gen_addr_spe_imm_index(ctx, sh);                                          \
    gen_op_load_gpr64_T1(rS(ctx->opcode));                                    \
    op_spe_ldst(spe_st##name);                                                \
}

#define GEN_SPE_STX(name)                                                     \
5379
static always_inline void gen_evst##name##x (DisasContext *ctx)               \
5380 5381
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5382
        GEN_EXCP_NO_AP(ctx);                                                  \
5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400
        return;                                                               \
    }                                                                         \
    gen_addr_reg_index(ctx);                                                  \
    gen_op_load_gpr64_T1(rS(ctx->opcode));                                    \
    op_spe_ldst(spe_st##name);                                                \
}

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

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

/* SPE arithmetic and logic */
#define GEN_SPEOP_ARITH2(name)                                                \
5401
static always_inline void gen_##name (DisasContext *ctx)                      \
5402 5403
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5404
        GEN_EXCP_NO_AP(ctx);                                                  \
5405 5406 5407 5408 5409 5410 5411 5412 5413
        return;                                                               \
    }                                                                         \
    gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
    gen_op_load_gpr64_T1(rB(ctx->opcode));                                    \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
}

#define GEN_SPEOP_ARITH1(name)                                                \
5414
static always_inline void gen_##name (DisasContext *ctx)                      \
5415 5416
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5417
        GEN_EXCP_NO_AP(ctx);                                                  \
5418 5419 5420 5421 5422 5423 5424 5425
        return;                                                               \
    }                                                                         \
    gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
}

#define GEN_SPEOP_COMP(name)                                                  \
5426
static always_inline void gen_##name (DisasContext *ctx)                      \
5427 5428
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5429
        GEN_EXCP_NO_AP(ctx);                                                  \
5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465
        return;                                                               \
    }                                                                         \
    gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
    gen_op_load_gpr64_T1(rB(ctx->opcode));                                    \
    gen_op_##name();                                                          \
    gen_op_store_T0_crf(crfD(ctx->opcode));                                   \
}

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

/* Arithmetic */
GEN_SPEOP_ARITH2(evaddw);
GEN_SPEOP_ARITH2(evsubfw);
GEN_SPEOP_ARITH1(evabs);
GEN_SPEOP_ARITH1(evneg);
GEN_SPEOP_ARITH1(evextsb);
GEN_SPEOP_ARITH1(evextsh);
GEN_SPEOP_ARITH1(evrndw);
GEN_SPEOP_ARITH1(evcntlzw);
GEN_SPEOP_ARITH1(evcntlsw);
5466
static always_inline void gen_brinc (DisasContext *ctx)
5467 5468
{
    /* Note: brinc is usable even if SPE is disabled */
5469 5470
    gen_op_load_gpr_T0(rA(ctx->opcode));
    gen_op_load_gpr_T1(rB(ctx->opcode));
5471
    gen_op_brinc();
5472
    gen_op_store_T0_gpr(rD(ctx->opcode));
5473 5474 5475
}

#define GEN_SPEOP_ARITH_IMM2(name)                                            \
5476
static always_inline void gen_##name##i (DisasContext *ctx)                   \
5477 5478
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5479
        GEN_EXCP_NO_AP(ctx);                                                  \
5480 5481 5482 5483 5484 5485 5486 5487 5488
        return;                                                               \
    }                                                                         \
    gen_op_load_gpr64_T0(rB(ctx->opcode));                                    \
    gen_op_splatwi_T1_64(rA(ctx->opcode));                                    \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
}

#define GEN_SPEOP_LOGIC_IMM2(name)                                            \
5489
static always_inline void gen_##name##i (DisasContext *ctx)                   \
5490 5491
{                                                                             \
    if (unlikely(!ctx->spe_enabled)) {                                        \
5492
        GEN_EXCP_NO_AP(ctx);                                                  \
5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511
        return;                                                               \
    }                                                                         \
    gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
    gen_op_splatwi_T1_64(rB(ctx->opcode));                                    \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
}

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

5512
static always_inline void gen_evsplati (DisasContext *ctx)
5513 5514 5515 5516 5517 5518 5519
{
    int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;

    gen_op_splatwi_T0_64(imm);
    gen_op_store_T0_gpr64(rD(ctx->opcode));
}

5520
static always_inline void gen_evsplatfi (DisasContext *ctx)
5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560
{
    uint32_t imm = rA(ctx->opcode) << 27;

    gen_op_splatwi_T0_64(imm);
    gen_op_store_T0_gpr64(rD(ctx->opcode));
}

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

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

5561
static always_inline void gen_evsel (DisasContext *ctx)
5562 5563
{
    if (unlikely(!ctx->spe_enabled)) {
5564
        GEN_EXCP_NO_AP(ctx);
5565 5566 5567 5568 5569 5570 5571 5572 5573
        return;
    }
    gen_op_load_crf_T0(ctx->opcode & 0x7);
    gen_op_load_gpr64_T0(rA(ctx->opcode));
    gen_op_load_gpr64_T1(rB(ctx->opcode));
    gen_op_evsel();
    gen_op_store_T0_gpr64(rD(ctx->opcode));
}

5574
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
5575 5576 5577
{
    gen_evsel(ctx);
}
5578
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
5579 5580 5581
{
    gen_evsel(ctx);
}
5582
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
5583 5584 5585
{
    gen_evsel(ctx);
}
5586
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
5587 5588 5589 5590 5591 5592 5593 5594 5595
{
    gen_evsel(ctx);
}

/* Load and stores */
#if defined(TARGET_PPC64)
/* In that case, we already have 64 bits load & stores
 * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
 */
5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627
#define gen_op_spe_ldd_raw           gen_op_ld_raw
#define gen_op_spe_ldd_user          gen_op_ld_user
#define gen_op_spe_ldd_kernel        gen_op_ld_kernel
#define gen_op_spe_ldd_hypv          gen_op_ld_hypv
#define gen_op_spe_ldd_64_raw        gen_op_ld_64_raw
#define gen_op_spe_ldd_64_user       gen_op_ld_64_user
#define gen_op_spe_ldd_64_kernel     gen_op_ld_64_kernel
#define gen_op_spe_ldd_64_hypv       gen_op_ld_64_hypv
#define gen_op_spe_ldd_le_raw        gen_op_ld_le_raw
#define gen_op_spe_ldd_le_user       gen_op_ld_le_user
#define gen_op_spe_ldd_le_kernel     gen_op_ld_le_kernel
#define gen_op_spe_ldd_le_hypv       gen_op_ld_le_hypv
#define gen_op_spe_ldd_le_64_raw     gen_op_ld_le_64_raw
#define gen_op_spe_ldd_le_64_user    gen_op_ld_le_64_user
#define gen_op_spe_ldd_le_64_kernel  gen_op_ld_le_64_kernel
#define gen_op_spe_ldd_le_64_hypv    gen_op_ld_le_64_hypv
#define gen_op_spe_stdd_raw          gen_op_std_raw
#define gen_op_spe_stdd_user         gen_op_std_user
#define gen_op_spe_stdd_kernel       gen_op_std_kernel
#define gen_op_spe_stdd_hypv         gen_op_std_hypv
#define gen_op_spe_stdd_64_raw       gen_op_std_64_raw
#define gen_op_spe_stdd_64_user      gen_op_std_64_user
#define gen_op_spe_stdd_64_kernel    gen_op_std_64_kernel
#define gen_op_spe_stdd_64_hypv      gen_op_std_64_hypv
#define gen_op_spe_stdd_le_raw       gen_op_std_le_raw
#define gen_op_spe_stdd_le_user      gen_op_std_le_user
#define gen_op_spe_stdd_le_kernel    gen_op_std_le_kernel
#define gen_op_spe_stdd_le_hypv      gen_op_std_le_hypv
#define gen_op_spe_stdd_le_64_raw    gen_op_std_le_64_raw
#define gen_op_spe_stdd_le_64_user   gen_op_std_le_64_user
#define gen_op_spe_stdd_le_64_kernel gen_op_std_le_64_kernel
#define gen_op_spe_stdd_le_64_hypv   gen_op_std_le_64_hypv
5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638
#endif /* defined(TARGET_PPC64) */
GEN_SPEOP_LDST(dd, 3);
GEN_SPEOP_LDST(dw, 3);
GEN_SPEOP_LDST(dh, 3);
GEN_SPEOP_LDST(whe, 2);
GEN_SPEOP_LD(whou, 2);
GEN_SPEOP_LD(whos, 2);
GEN_SPEOP_ST(who, 2);

#if defined(TARGET_PPC64)
/* In that case, spe_stwwo is equivalent to stw */
5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652
#define gen_op_spe_stwwo_raw          gen_op_stw_raw
#define gen_op_spe_stwwo_user         gen_op_stw_user
#define gen_op_spe_stwwo_kernel       gen_op_stw_kernel
#define gen_op_spe_stwwo_hypv         gen_op_stw_hypv
#define gen_op_spe_stwwo_le_raw       gen_op_stw_le_raw
#define gen_op_spe_stwwo_le_user      gen_op_stw_le_user
#define gen_op_spe_stwwo_le_kernel    gen_op_stw_le_kernel
#define gen_op_spe_stwwo_le_hypv      gen_op_stw_le_hypv
#define gen_op_spe_stwwo_64_raw       gen_op_stw_64_raw
#define gen_op_spe_stwwo_64_user      gen_op_stw_64_user
#define gen_op_spe_stwwo_64_kernel    gen_op_stw_64_kernel
#define gen_op_spe_stwwo_64_hypv      gen_op_stw_64_hypv
#define gen_op_spe_stwwo_le_64_raw    gen_op_stw_le_64_raw
#define gen_op_spe_stwwo_le_64_user   gen_op_stw_le_64_user
5653
#define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
5654
#define gen_op_spe_stwwo_le_64_hypv   gen_op_stw_le_64_hypv
5655 5656
#endif
#define _GEN_OP_SPE_STWWE(suffix)                                             \
5657
static always_inline void gen_op_spe_stwwe_##suffix (void)                    \
5658 5659 5660 5661 5662
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_##suffix();                                              \
}
#define _GEN_OP_SPE_STWWE_LE(suffix)                                          \
5663
static always_inline void gen_op_spe_stwwe_le_##suffix (void)                 \
5664 5665 5666 5667 5668 5669 5670 5671
{                                                                             \
    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);                                                 \
5672
static always_inline void gen_op_spe_stwwe_64_##suffix (void)                 \
5673 5674 5675 5676
{                                                                             \
    gen_op_srli32_T1_64();                                                    \
    gen_op_spe_stwwo_64_##suffix();                                           \
}                                                                             \
5677
static always_inline void gen_op_spe_stwwe_le_64_##suffix (void)              \
5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690
{                                                                             \
    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);
5691 5692
GEN_OP_SPE_STWWE(kernel);
GEN_OP_SPE_STWWE(hypv);
5693 5694 5695 5696 5697
#endif /* defined(CONFIG_USER_ONLY) */
GEN_SPEOP_ST(wwe, 2);
GEN_SPEOP_ST(wwo, 2);

#define GEN_SPE_LDSPLAT(name, op, suffix)                                     \
5698
static always_inline void gen_op_spe_l##name##_##suffix (void)                \
5699 5700 5701 5702 5703 5704
{                                                                             \
    gen_op_##op##_##suffix();                                                 \
    gen_op_splatw_T1_64();                                                    \
}

#define GEN_OP_SPE_LHE(suffix)                                                \
5705
static always_inline void gen_op_spe_lhe_##suffix (void)                      \
5706 5707 5708 5709 5710 5711
{                                                                             \
    gen_op_spe_lh_##suffix();                                                 \
    gen_op_sli16_T1_64();                                                     \
}

#define GEN_OP_SPE_LHX(suffix)                                                \
5712
static always_inline void gen_op_spe_lhx_##suffix (void)                      \
5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742
{                                                                             \
    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);
5743 5744
GEN_OP_SPE_LHE(kernel);
GEN_OP_SPE_LHE(hypv);
5745
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
5746 5747
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, hypv);
5748
GEN_OP_SPE_LHE(le_user);
5749 5750
GEN_OP_SPE_LHE(le_kernel);
GEN_OP_SPE_LHE(le_hypv);
5751
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
5752 5753
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_hypv);
5754
GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
5755 5756
GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, hypv);
5757
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
5758 5759
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_hypv);
5760
GEN_OP_SPE_LHX(user);
5761 5762
GEN_OP_SPE_LHX(kernel);
GEN_OP_SPE_LHX(hypv);
5763
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
5764 5765
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, hypv);
5766
GEN_OP_SPE_LHX(le_user);
5767 5768
GEN_OP_SPE_LHX(le_kernel);
GEN_OP_SPE_LHX(le_hypv);
5769
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
5770 5771
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_hypv);
5772 5773
#if defined(TARGET_PPC64)
GEN_OP_SPE_LHE(64_user);
5774 5775
GEN_OP_SPE_LHE(64_kernel);
GEN_OP_SPE_LHE(64_hypv);
5776
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
5777 5778
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_hypv);
5779
GEN_OP_SPE_LHE(le_64_user);
5780 5781
GEN_OP_SPE_LHE(le_64_kernel);
GEN_OP_SPE_LHE(le_64_hypv);
5782
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
5783 5784
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_hypv);
5785
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
5786 5787
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_hypv);
5788
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
5789 5790
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_hypv);
5791
GEN_OP_SPE_LHX(64_user);
5792 5793
GEN_OP_SPE_LHX(64_kernel);
GEN_OP_SPE_LHX(64_hypv);
5794
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
5795 5796
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_hypv);
5797
GEN_OP_SPE_LHX(le_64_user);
5798 5799
GEN_OP_SPE_LHX(le_64_kernel);
GEN_OP_SPE_LHX(le_64_hypv);
5800
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
5801 5802
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_hypv);
5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907
#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)                                               \
5908
static always_inline void gen_##name (DisasContext *ctx)                      \
5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988
{                                                                             \
    gen_op_load_gpr64_T0(rB(ctx->opcode));                                    \
    gen_op_##name();                                                          \
    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
}

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

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

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

/* Opcodes definitions */
5989
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054
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); //
GEN_SPE(efsctuiz,       efsctsiz,      0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //

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

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

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

B
bellard 已提交
6055 6056 6057
/* End opcode list */
GEN_OPCODE_MARK(end);

6058
#include "translate_init.c"
6059
#include "helper_regs.h"
B
bellard 已提交
6060

6061
/*****************************************************************************/
6062
/* Misc PowerPC helpers */
6063 6064 6065
void cpu_dump_state (CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
B
bellard 已提交
6066
{
6067 6068 6069
#define RGPL  4
#define RFPL  4

B
bellard 已提交
6070 6071
    int i;

J
j_mayer 已提交
6072 6073
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
                env->nip, env->lr, env->ctr, hreg_load_xer(env));
6074 6075
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
6076
#if !defined(NO_TIMER_DUMP)
J
j_mayer 已提交
6077
    cpu_fprintf(f, "TB %08x %08x "
6078 6079 6080 6081
#if !defined(CONFIG_USER_ONLY)
                "DECR %08x"
#endif
                "\n",
J
j_mayer 已提交
6082
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
6083 6084 6085 6086
#if !defined(CONFIG_USER_ONLY)
                , cpu_ppc_load_decr(env)
#endif
                );
J
j_mayer 已提交
6087
#endif
6088
    for (i = 0; i < 32; i++) {
6089 6090
        if ((i & (RGPL - 1)) == 0)
            cpu_fprintf(f, "GPR%02d", i);
6091
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
6092
        if ((i & (RGPL - 1)) == (RGPL - 1))
B
bellard 已提交
6093
            cpu_fprintf(f, "\n");
6094
    }
6095
    cpu_fprintf(f, "CR ");
6096
    for (i = 0; i < 8; i++)
B
bellard 已提交
6097 6098
        cpu_fprintf(f, "%01x", env->crf[i]);
    cpu_fprintf(f, "  [");
6099 6100 6101 6102 6103 6104 6105 6106
    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 已提交
6107
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
6108
    }
6109
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
6110 6111 6112
    for (i = 0; i < 32; i++) {
        if ((i & (RFPL - 1)) == 0)
            cpu_fprintf(f, "FPR%02d", i);
B
bellard 已提交
6113
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
6114
        if ((i & (RFPL - 1)) == (RFPL - 1))
B
bellard 已提交
6115
            cpu_fprintf(f, "\n");
B
bellard 已提交
6116
    }
6117
#if !defined(CONFIG_USER_ONLY)
6118
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
6119
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
6120
#endif
B
bellard 已提交
6121

6122 6123
#undef RGPL
#undef RFPL
B
bellard 已提交
6124 6125
}

6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172
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
}

6173
/*****************************************************************************/
6174 6175 6176
static always_inline int gen_intermediate_code_internal (CPUState *env,
                                                         TranslationBlock *tb,
                                                         int search_pc)
B
bellard 已提交
6177
{
6178
    DisasContext ctx, *ctxp = &ctx;
B
bellard 已提交
6179
    opc_handler_t **table, *handler;
B
bellard 已提交
6180
    target_ulong pc_start;
B
bellard 已提交
6181
    uint16_t *gen_opc_end;
6182
    int supervisor, little_endian;
B
bellard 已提交
6183
    int j, lj = -1;
P
pbrook 已提交
6184 6185
    int num_insns;
    int max_insns;
B
bellard 已提交
6186 6187 6188

    pc_start = tb->pc;
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6189 6190 6191
#if defined(OPTIMIZE_FPRF_UPDATE)
    gen_fprf_ptr = gen_fprf_buf;
#endif
B
bellard 已提交
6192
    ctx.nip = pc_start;
B
bellard 已提交
6193
    ctx.tb = tb;
6194
    ctx.exception = POWERPC_EXCP_NONE;
6195
    ctx.spr_cb = env->spr_cb;
6196 6197
    supervisor = env->mmu_idx;
#if !defined(CONFIG_USER_ONLY)
6198
    ctx.supervisor = supervisor;
6199
#endif
6200
    little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
6201 6202
#if defined(TARGET_PPC64)
    ctx.sf_mode = msr_sf;
6203
    ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
6204
#else
6205
    ctx.mem_idx = (supervisor << 1) | little_endian;
6206
#endif
6207
    ctx.dcache_line_size = env->dcache_line_size;
B
bellard 已提交
6208
    ctx.fpu_enabled = msr_fp;
6209
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
6210 6211 6212
        ctx.spe_enabled = msr_spe;
    else
        ctx.spe_enabled = 0;
6213 6214 6215 6216
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
        ctx.altivec_enabled = msr_vr;
    else
        ctx.altivec_enabled = 0;
6217
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
6218
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
6219
    else
6220
        ctx.singlestep_enabled = 0;
6221
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
6222 6223 6224
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
    if (unlikely(env->singlestep_enabled))
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
6225
#if defined (DO_SINGLE_STEP) && 0
6226 6227 6228
    /* Single step trace mode */
    msr_se = 1;
#endif
P
pbrook 已提交
6229 6230 6231 6232 6233 6234
    num_insns = 0;
    max_insns = tb->cflags & CF_COUNT_MASK;
    if (max_insns == 0)
        max_insns = CF_COUNT_MASK;

    gen_icount_start();
6235
    /* Set env in case of segfault during code fetch */
6236
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
6237 6238
        if (unlikely(env->nb_breakpoints > 0)) {
            for (j = 0; j < env->nb_breakpoints; j++) {
6239
                if (env->breakpoints[j] == ctx.nip) {
6240
                    gen_update_nip(&ctx, ctx.nip);
6241 6242 6243 6244 6245
                    gen_op_debug();
                    break;
                }
            }
        }
6246
        if (unlikely(search_pc)) {
B
bellard 已提交
6247 6248 6249 6250 6251
            j = gen_opc_ptr - gen_opc_buf;
            if (lj < j) {
                lj++;
                while (lj < j)
                    gen_opc_instr_start[lj++] = 0;
B
bellard 已提交
6252
                gen_opc_pc[lj] = ctx.nip;
B
bellard 已提交
6253
                gen_opc_instr_start[lj] = 1;
P
pbrook 已提交
6254
                gen_opc_icount[lj] = num_insns;
B
bellard 已提交
6255 6256
            }
        }
6257 6258
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
B
bellard 已提交
6259
            fprintf(logfile, "----------------\n");
6260
            fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
6261
                    ctx.nip, supervisor, (int)msr_ir);
6262 6263
        }
#endif
P
pbrook 已提交
6264 6265
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
            gen_io_start();
6266 6267 6268 6269
        if (unlikely(little_endian)) {
            ctx.opcode = bswap32(ldl_code(ctx.nip));
        } else {
            ctx.opcode = ldl_code(ctx.nip);
6270
        }
6271 6272
#if defined PPC_DEBUG_DISAS
        if (loglevel & CPU_LOG_TB_IN_ASM) {
6273
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6274
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
6275
                    opc3(ctx.opcode), little_endian ? "little" : "big");
B
bellard 已提交
6276 6277
        }
#endif
B
bellard 已提交
6278
        ctx.nip += 4;
6279
        table = env->opcodes;
P
pbrook 已提交
6280
        num_insns++;
B
bellard 已提交
6281 6282 6283 6284 6285 6286 6287 6288 6289 6290
        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 ? */
6291
        if (unlikely(handler->handler == &gen_invalid)) {
J
j_mayer 已提交
6292
            if (loglevel != 0) {
6293
                fprintf(logfile, "invalid/unsupported opcode: "
6294
                        "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
6295
                        opc1(ctx.opcode), opc2(ctx.opcode),
6296
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
6297 6298
            } else {
                printf("invalid/unsupported opcode: "
6299
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
B
bellard 已提交
6300
                       opc1(ctx.opcode), opc2(ctx.opcode),
6301
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
B
bellard 已提交
6302
            }
6303 6304
        } else {
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
J
j_mayer 已提交
6305
                if (loglevel != 0) {
B
bellard 已提交
6306
                    fprintf(logfile, "invalid bits: %08x for opcode: "
6307
                            "%02x - %02x - %02x (%08x) " ADDRX "\n",
B
bellard 已提交
6308 6309
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
                            opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
6310
                            ctx.opcode, ctx.nip - 4);
6311 6312
                } else {
                    printf("invalid bits: %08x for opcode: "
6313
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
6314 6315
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
                           opc2(ctx.opcode), opc3(ctx.opcode),
B
bellard 已提交
6316
                           ctx.opcode, ctx.nip - 4);
6317
                }
6318
                GEN_EXCP_INVAL(ctxp);
B
bellard 已提交
6319
                break;
B
bellard 已提交
6320 6321
            }
        }
B
bellard 已提交
6322
        (*(handler->handler))(&ctx);
6323 6324 6325
#if defined(DO_PPC_STATISTICS)
        handler->count++;
#endif
6326
        /* Check trace mode exceptions */
6327 6328 6329 6330 6331
        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)) {
6332
            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
6333
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
P
pbrook 已提交
6334 6335
                            (env->singlestep_enabled) ||
                            num_insns >= max_insns)) {
6336 6337 6338
            /* if we reach a page boundary or are single stepping, stop
             * generation
             */
6339
            break;
6340
        }
6341 6342 6343 6344
#if defined (DO_SINGLE_STEP)
        break;
#endif
    }
P
pbrook 已提交
6345 6346
    if (tb->cflags & CF_LAST_IO)
        gen_io_end();
6347
    if (ctx.exception == POWERPC_EXCP_NONE) {
6348
        gen_goto_tb(&ctx, 0, ctx.nip);
6349
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
6350 6351 6352 6353
        if (unlikely(env->singlestep_enabled)) {
            gen_update_nip(&ctx, ctx.nip);
            gen_op_debug();
        }
6354
        /* Generate the return instruction */
B
bellard 已提交
6355
        tcg_gen_exit_tb(0);
6356
    }
P
pbrook 已提交
6357
    gen_icount_end(tb, num_insns);
B
bellard 已提交
6358
    *gen_opc_ptr = INDEX_op_end;
6359
    if (unlikely(search_pc)) {
6360 6361 6362 6363 6364
        j = gen_opc_ptr - gen_opc_buf;
        lj++;
        while (lj <= j)
            gen_opc_instr_start[lj++] = 0;
    } else {
B
bellard 已提交
6365
        tb->size = ctx.nip - pc_start;
P
pbrook 已提交
6366
        tb->icount = num_insns;
6367
    }
6368
#if defined(DEBUG_DISAS)
6369
    if (loglevel & CPU_LOG_TB_CPU) {
6370
        fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
B
bellard 已提交
6371
        cpu_dump_state(env, logfile, fprintf, 0);
6372 6373
    }
    if (loglevel & CPU_LOG_TB_IN_ASM) {
6374
        int flags;
6375
        flags = env->bfd_mach;
6376
        flags |= little_endian << 16;
B
bellard 已提交
6377
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6378
        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
B
bellard 已提交
6379
        fprintf(logfile, "\n");
6380
    }
B
bellard 已提交
6381 6382 6383 6384
#endif
    return 0;
}

6385
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
6386 6387 6388 6389
{
    return gen_intermediate_code_internal(env, tb, 0);
}

6390
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
B
bellard 已提交
6391 6392 6393
{
    return gen_intermediate_code_internal(env, tb, 1);
}
A
aurel32 已提交
6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435

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