translate.c 360 KB
Newer Older
bellard's avatar
bellard committed
1
/*
2
 *  PowerPC emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
Scott Wood's avatar
Scott Wood committed
5
 *  Copyright (C) 2011 Freescale Semiconductor, Inc.
bellard's avatar
bellard committed
6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard's avatar
bellard committed
19
 */
bellard's avatar
bellard committed
20

bellard's avatar
bellard committed
21 22
#include "cpu.h"
#include "disas.h"
bellard's avatar
bellard committed
23
#include "tcg-op.h"
aurel32's avatar
aurel32 committed
24
#include "host-utils.h"
bellard's avatar
bellard committed
25

pbrook's avatar
pbrook committed
26 27 28 29
#include "helper.h"
#define GEN_HELPER 1
#include "helper.h"

30 31 32 33
#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2
#define GDBSTUB_SINGLE_STEP 0x4

34
/* Include definitions for instructions classes and implementations flags */
35
//#define PPC_DEBUG_DISAS
36
//#define DO_PPC_STATISTICS
bellard's avatar
bellard committed
37

38
#ifdef PPC_DEBUG_DISAS
39
#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
40 41 42
#else
#  define LOG_DISAS(...) do { } while (0)
#endif
43 44
/*****************************************************************************/
/* Code translation helpers                                                  */
bellard's avatar
bellard committed
45

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

pbrook's avatar
pbrook committed
74 75 76 77
#include "gen-icount.h"

void ppc_translate_init(void)
{
aurel32's avatar
aurel32 committed
78 79
    int i;
    char* p;
80
    size_t cpu_reg_names_size;
pbrook's avatar
pbrook committed
81
    static int done_init = 0;
aurel32's avatar
aurel32 committed
82

pbrook's avatar
pbrook committed
83 84
    if (done_init)
        return;
aurel32's avatar
aurel32 committed
85

pbrook's avatar
pbrook committed
86 87
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");

aurel32's avatar
aurel32 committed
88
    p = cpu_reg_names;
89
    cpu_reg_names_size = sizeof(cpu_reg_names);
aurel32's avatar
aurel32 committed
90 91

    for (i = 0; i < 8; i++) {
92
        snprintf(p, cpu_reg_names_size, "crf%d", i);
pbrook's avatar
pbrook committed
93
        cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
94
                                            offsetof(CPUPPCState, crf[i]), p);
aurel32's avatar
aurel32 committed
95
        p += 5;
96
        cpu_reg_names_size -= 5;
aurel32's avatar
aurel32 committed
97 98
    }

aurel32's avatar
aurel32 committed
99
    for (i = 0; i < 32; i++) {
100
        snprintf(p, cpu_reg_names_size, "r%d", i);
pbrook's avatar
pbrook committed
101
        cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
102
                                        offsetof(CPUPPCState, gpr[i]), p);
aurel32's avatar
aurel32 committed
103
        p += (i < 10) ? 3 : 4;
104
        cpu_reg_names_size -= (i < 10) ? 3 : 4;
aurel32's avatar
aurel32 committed
105
#if !defined(TARGET_PPC64)
106
        snprintf(p, cpu_reg_names_size, "r%dH", i);
pbrook's avatar
pbrook committed
107
        cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
108
                                             offsetof(CPUPPCState, gprh[i]), p);
aurel32's avatar
aurel32 committed
109
        p += (i < 10) ? 4 : 5;
110
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
aurel32's avatar
aurel32 committed
111
#endif
112

113
        snprintf(p, cpu_reg_names_size, "fp%d", i);
pbrook's avatar
pbrook committed
114
        cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
115
                                            offsetof(CPUPPCState, fpr[i]), p);
aurel32's avatar
aurel32 committed
116
        p += (i < 10) ? 4 : 5;
117
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
aurel32's avatar
aurel32 committed
118

119
        snprintf(p, cpu_reg_names_size, "avr%dH", i);
120
#ifdef HOST_WORDS_BIGENDIAN
121
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
122
                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
123
#else
pbrook's avatar
pbrook committed
124
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
125
                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
126
#endif
127
        p += (i < 10) ? 6 : 7;
128
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
aurel32's avatar
aurel32 committed
129

130
        snprintf(p, cpu_reg_names_size, "avr%dL", i);
131
#ifdef HOST_WORDS_BIGENDIAN
132
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
133
                                             offsetof(CPUPPCState, avr[i].u64[1]), p);
134
#else
pbrook's avatar
pbrook committed
135
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
136
                                             offsetof(CPUPPCState, avr[i].u64[0]), p);
137
#endif
138
        p += (i < 10) ? 6 : 7;
139
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
aurel32's avatar
aurel32 committed
140
    }
aurel32's avatar
aurel32 committed
141

pbrook's avatar
pbrook committed
142
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
143
                                 offsetof(CPUPPCState, nip), "nip");
aurel32's avatar
aurel32 committed
144

145
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
146
                                 offsetof(CPUPPCState, msr), "msr");
147

pbrook's avatar
pbrook committed
148
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
149
                                 offsetof(CPUPPCState, ctr), "ctr");
aurel32's avatar
aurel32 committed
150

pbrook's avatar
pbrook committed
151
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
152
                                offsetof(CPUPPCState, lr), "lr");
aurel32's avatar
aurel32 committed
153

David Gibson's avatar
David Gibson committed
154 155
#if defined(TARGET_PPC64)
    cpu_cfar = tcg_global_mem_new(TCG_AREG0,
156
                                  offsetof(CPUPPCState, cfar), "cfar");
David Gibson's avatar
David Gibson committed
157 158
#endif

pbrook's avatar
pbrook committed
159
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
160
                                 offsetof(CPUPPCState, xer), "xer");
161

162
    cpu_reserve = tcg_global_mem_new(TCG_AREG0,
163
                                     offsetof(CPUPPCState, reserve_addr),
164
                                     "reserve_addr");
165

pbrook's avatar
pbrook committed
166
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
167
                                       offsetof(CPUPPCState, fpscr), "fpscr");
168

aurel32's avatar
aurel32 committed
169
    cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
170
                                             offsetof(CPUPPCState, access_type), "access_type");
aurel32's avatar
aurel32 committed
171

aurel32's avatar
aurel32 committed
172
    /* register helpers */
pbrook's avatar
pbrook committed
173
#define GEN_HELPER 2
aurel32's avatar
aurel32 committed
174 175
#include "helper.h"

pbrook's avatar
pbrook committed
176 177 178
    done_init = 1;
}

bellard's avatar
bellard committed
179 180 181
/* internal defines */
typedef struct DisasContext {
    struct TranslationBlock *tb;
bellard's avatar
bellard committed
182
    target_ulong nip;
bellard's avatar
bellard committed
183
    uint32_t opcode;
184
    uint32_t exception;
bellard's avatar
bellard committed
185 186
    /* Routine used to access memory */
    int mem_idx;
aurel32's avatar
aurel32 committed
187
    int access_type;
bellard's avatar
bellard committed
188
    /* Translation flags */
aurel32's avatar
aurel32 committed
189
    int le_mode;
190 191
#if defined(TARGET_PPC64)
    int sf_mode;
David Gibson's avatar
David Gibson committed
192
    int has_cfar;
193
#endif
bellard's avatar
bellard committed
194
    int fpu_enabled;
195
    int altivec_enabled;
196
    int spe_enabled;
197
    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
198
    int singlestep_enabled;
bellard's avatar
bellard committed
199 200
} DisasContext;

201
struct opc_handler_t {
202 203 204 205
    /* invalid bits for instruction 1 (Rc(opcode) == 0) */
    uint32_t inval1;
    /* invalid bits for instruction 2 (Rc(opcode) == 1) */
    uint32_t inval2;
206
    /* instruction type */
207
    uint64_t type;
208 209
    /* extended instruction type */
    uint64_t type2;
bellard's avatar
bellard committed
210 211
    /* handler */
    void (*handler)(DisasContext *ctx);
212
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
213
    const char *oname;
214 215
#endif
#if defined(DO_PPC_STATISTICS)
216 217
    uint64_t count;
#endif
218
};
bellard's avatar
bellard committed
219

Blue Swirl's avatar
Blue Swirl committed
220
static inline void gen_reset_fpstatus(void)
221
{
222
    gen_helper_reset_fpstatus(cpu_env);
223 224
}

Blue Swirl's avatar
Blue Swirl committed
225
static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
226
{
227
    TCGv_i32 t0 = tcg_temp_new_i32();
aurel32's avatar
aurel32 committed
228

229 230
    if (set_fprf != 0) {
        /* This case might be optimized later */
231
        tcg_gen_movi_i32(t0, 1);
232
        gen_helper_compute_fprf(t0, cpu_env, arg, t0);
pbrook's avatar
pbrook committed
233
        if (unlikely(set_rc)) {
234
            tcg_gen_mov_i32(cpu_crf[1], t0);
pbrook's avatar
pbrook committed
235
        }
236
        gen_helper_float_check_status(cpu_env);
237 238
    } else if (unlikely(set_rc)) {
        /* We always need to compute fpcc */
239
        tcg_gen_movi_i32(t0, 0);
240
        gen_helper_compute_fprf(t0, cpu_env, arg, t0);
241
        tcg_gen_mov_i32(cpu_crf[1], t0);
242
    }
aurel32's avatar
aurel32 committed
243

244
    tcg_temp_free_i32(t0);
245 246
}

Blue Swirl's avatar
Blue Swirl committed
247
static inline void gen_set_access_type(DisasContext *ctx, int access_type)
aurel32's avatar
aurel32 committed
248
{
aurel32's avatar
aurel32 committed
249 250 251 252
    if (ctx->access_type != access_type) {
        tcg_gen_movi_i32(cpu_access_type, access_type);
        ctx->access_type = access_type;
    }
aurel32's avatar
aurel32 committed
253 254
}

Blue Swirl's avatar
Blue Swirl committed
255
static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
256 257 258
{
#if defined(TARGET_PPC64)
    if (ctx->sf_mode)
aurel32's avatar
aurel32 committed
259
        tcg_gen_movi_tl(cpu_nip, nip);
260 261
    else
#endif
aurel32's avatar
aurel32 committed
262
        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
263 264
}

Blue Swirl's avatar
Blue Swirl committed
265
static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
aurel32's avatar
aurel32 committed
266 267 268 269 270 271 272
{
    TCGv_i32 t0, t1;
    if (ctx->exception == POWERPC_EXCP_NONE) {
        gen_update_nip(ctx, ctx->nip);
    }
    t0 = tcg_const_i32(excp);
    t1 = tcg_const_i32(error);
273
    gen_helper_raise_exception_err(cpu_env, t0, t1);
aurel32's avatar
aurel32 committed
274 275 276 277
    tcg_temp_free_i32(t0);
    tcg_temp_free_i32(t1);
    ctx->exception = (excp);
}
278

Blue Swirl's avatar
Blue Swirl committed
279
static inline void gen_exception(DisasContext *ctx, uint32_t excp)
aurel32's avatar
aurel32 committed
280 281 282 283 284 285
{
    TCGv_i32 t0;
    if (ctx->exception == POWERPC_EXCP_NONE) {
        gen_update_nip(ctx, ctx->nip);
    }
    t0 = tcg_const_i32(excp);
286
    gen_helper_raise_exception(cpu_env, t0);
aurel32's avatar
aurel32 committed
287 288 289
    tcg_temp_free_i32(t0);
    ctx->exception = (excp);
}
290

Blue Swirl's avatar
Blue Swirl committed
291
static inline void gen_debug_exception(DisasContext *ctx)
aurel32's avatar
aurel32 committed
292 293
{
    TCGv_i32 t0;
blueswir1's avatar
blueswir1 committed
294

295 296
    if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
        (ctx->exception != POWERPC_EXCP_SYNC)) {
blueswir1's avatar
blueswir1 committed
297
        gen_update_nip(ctx, ctx->nip);
298
    }
aurel32's avatar
aurel32 committed
299
    t0 = tcg_const_i32(EXCP_DEBUG);
300
    gen_helper_raise_exception(cpu_env, t0);
aurel32's avatar
aurel32 committed
301 302
    tcg_temp_free_i32(t0);
}
303

Blue Swirl's avatar
Blue Swirl committed
304
static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
aurel32's avatar
aurel32 committed
305 306 307
{
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
}
308

309
/* Stop translation */
Blue Swirl's avatar
Blue Swirl committed
310
static inline void gen_stop_exception(DisasContext *ctx)
311
{
312
    gen_update_nip(ctx, ctx->nip);
313
    ctx->exception = POWERPC_EXCP_STOP;
314 315
}

316
/* No need to update nip here, as execution flow will change */
Blue Swirl's avatar
Blue Swirl committed
317
static inline void gen_sync_exception(DisasContext *ctx)
318
{
319
    ctx->exception = POWERPC_EXCP_SYNC;
320 321
}

bellard's avatar
bellard committed
322
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
323 324 325 326
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)

#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2)             \
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
bellard's avatar
bellard committed
327

328
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
329 330 331 332
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)

#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2)      \
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
333

334
typedef struct opcode_t {
bellard's avatar
bellard committed
335
    unsigned char opc1, opc2, opc3;
ths's avatar
ths committed
336
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
337 338 339 340
    unsigned char pad[5];
#else
    unsigned char pad[1];
#endif
341
    opc_handler_t handler;
342
    const char *oname;
343
} opcode_t;
bellard's avatar
bellard committed
344

345
/*****************************************************************************/
bellard's avatar
bellard committed
346 347
/***                           Instruction decoding                        ***/
#define EXTRACT_HELPER(name, shift, nb)                                       \
Blue Swirl's avatar
Blue Swirl committed
348
static inline uint32_t name(uint32_t opcode)                                  \
bellard's avatar
bellard committed
349 350 351 352 353
{                                                                             \
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
}

#define EXTRACT_SHELPER(name, shift, nb)                                      \
Blue Swirl's avatar
Blue Swirl committed
354
static inline int32_t name(uint32_t opcode)                                   \
bellard's avatar
bellard committed
355
{                                                                             \
356
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
bellard's avatar
bellard committed
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
}

/* 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 */
384
EXTRACT_HELPER(_SPR, 11, 10);
Blue Swirl's avatar
Blue Swirl committed
385
static inline uint32_t SPR(uint32_t opcode)
386 387 388 389 390
{
    uint32_t sprn = _SPR(opcode);

    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
}
bellard's avatar
bellard committed
391 392 393 394 395 396
/***                              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);
397 398
/* 5 bits signed immediate value */
EXTRACT_HELPER(SIMM5, 16, 5);
399 400
/* 5 bits signed immediate value */
EXTRACT_HELPER(UIMM5, 16, 5);
bellard's avatar
bellard committed
401 402 403 404
/* Bit count */
EXTRACT_HELPER(NB, 11, 5);
/* Shift count */
EXTRACT_HELPER(SH, 11, 5);
aurel32's avatar
aurel32 committed
405 406
/* Vector shift count */
EXTRACT_HELPER(VSH, 6, 4);
bellard's avatar
bellard committed
407 408 409 410
/* Mask start */
EXTRACT_HELPER(MB, 6, 5);
/* Mask end */
EXTRACT_HELPER(ME, 1, 5);
bellard's avatar
bellard committed
411 412
/* Trap operand */
EXTRACT_HELPER(TO, 21, 5);
bellard's avatar
bellard committed
413 414 415 416

EXTRACT_HELPER(CRM, 12, 8);
EXTRACT_HELPER(FM, 17, 8);
EXTRACT_HELPER(SR, 16, 4);
aurel32's avatar
aurel32 committed
417
EXTRACT_HELPER(FPIMM, 12, 4);
bellard's avatar
bellard committed
418

bellard's avatar
bellard committed
419 420 421 422
/***                            Jump target decoding                       ***/
/* Displacement */
EXTRACT_SHELPER(d, 0, 16);
/* Immediate address */
Blue Swirl's avatar
Blue Swirl committed
423
static inline target_ulong LI(uint32_t opcode)
bellard's avatar
bellard committed
424 425 426 427
{
    return (opcode >> 0) & 0x03FFFFFC;
}

Blue Swirl's avatar
Blue Swirl committed
428
static inline uint32_t BD(uint32_t opcode)
bellard's avatar
bellard committed
429 430 431 432 433 434 435 436 437 438 439 440
{
    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 */
Blue Swirl's avatar
Blue Swirl committed
441
static inline target_ulong MASK(uint32_t start, uint32_t end)
bellard's avatar
bellard committed
442
{
443
    target_ulong ret;
bellard's avatar
bellard committed
444

445 446
#if defined(TARGET_PPC64)
    if (likely(start == 0)) {
447
        ret = UINT64_MAX << (63 - end);
448
    } else if (likely(end == 63)) {
449
        ret = UINT64_MAX >> start;
450 451 452
    }
#else
    if (likely(start == 0)) {
453
        ret = UINT32_MAX << (31  - end);
454
    } else if (likely(end == 31)) {
455
        ret = UINT32_MAX >> start;
456 457 458 459 460 461 462 463
    }
#endif
    else {
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
            (((target_ulong)(-1ULL) >> (end)) >> 1);
        if (unlikely(start > end))
            return ~ret;
    }
bellard's avatar
bellard committed
464 465 466 467

    return ret;
}

468 469
/*****************************************************************************/
/* PowerPC instructions table                                                */
bellard's avatar
bellard committed
470

471
#if defined(DO_PPC_STATISTICS)
472
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
473
{                                                                             \
bellard's avatar
bellard committed
474 475 476
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
477
    .pad  = { 0, },                                                           \
bellard's avatar
bellard committed
478
    .handler = {                                                              \
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
        .inval1  = invl,                                                      \
        .type = _typ,                                                         \
        .type2 = _typ2,                                                       \
        .handler = &gen_##name,                                               \
        .oname = stringify(name),                                             \
    },                                                                        \
    .oname = stringify(name),                                                 \
}
#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval1  = invl1,                                                     \
        .inval2  = invl2,                                                     \
496
        .type = _typ,                                                         \
497
        .type2 = _typ2,                                                       \
bellard's avatar
bellard committed
498
        .handler = &gen_##name,                                               \
499
        .oname = stringify(name),                                             \
bellard's avatar
bellard committed
500
    },                                                                        \
501
    .oname = stringify(name),                                                 \
bellard's avatar
bellard committed
502
}
503
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
504
{                                                                             \
505 506 507 508 509
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
510
        .inval1  = invl,                                                      \
511
        .type = _typ,                                                         \
512
        .type2 = _typ2,                                                       \
513 514 515 516 517
        .handler = &gen_##name,                                               \
        .oname = onam,                                                        \
    },                                                                        \
    .oname = onam,                                                            \
}
518
#else
519
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)                    \
520
{                                                                             \
521 522 523 524 525
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
        .inval1  = invl,                                                      \
        .type = _typ,                                                         \
        .type2 = _typ2,                                                       \
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = stringify(name),                                                 \
}
#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2)       \
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
        .inval1  = invl1,                                                     \
        .inval2  = invl2,                                                     \
542
        .type = _typ,                                                         \
543
        .type2 = _typ2,                                                       \
544
        .handler = &gen_##name,                                               \
545 546 547
    },                                                                        \
    .oname = stringify(name),                                                 \
}
548
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2)             \
549 550 551 552 553 554
{                                                                             \
    .opc1 = op1,                                                              \
    .opc2 = op2,                                                              \
    .opc3 = op3,                                                              \
    .pad  = { 0, },                                                           \
    .handler = {                                                              \
555
        .inval1  = invl,                                                      \
556
        .type = _typ,                                                         \
557
        .type2 = _typ2,                                                       \
558 559 560 561 562
        .handler = &gen_##name,                                               \
    },                                                                        \
    .oname = onam,                                                            \
}
#endif
563

564
/* SPR load/store helpers */
Blue Swirl's avatar
Blue Swirl committed
565
static inline void gen_load_spr(TCGv t, int reg)
566
{
567
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
568
}
569

Blue Swirl's avatar
Blue Swirl committed
570
static inline void gen_store_spr(int reg, TCGv t)
571
{
572
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
573
}
574

575
/* Invalid instruction */
Blue Swirl's avatar
Blue Swirl committed
576
static void gen_invalid(DisasContext *ctx)
577
{
aurel32's avatar
aurel32 committed
578
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
579 580
}

581
static opc_handler_t invalid_handler = {
582 583
    .inval1  = 0xFFFFFFFF,
    .inval2  = 0xFFFFFFFF,
584
    .type    = PPC_NONE,
585
    .type2   = PPC_NONE,
bellard's avatar
bellard committed
586 587 588
    .handler = gen_invalid,
};

589 590
/***                           Integer comparison                          ***/

Blue Swirl's avatar
Blue Swirl committed
591
static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
592 593 594
{
    int l1, l2, l3;

595 596
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
597 598 599 600 601 602
    tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);

    l1 = gen_new_label();
    l2 = gen_new_label();
    l3 = gen_new_label();
    if (s) {
603 604
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
605
    } else {
606 607
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
608 609 610 611 612 613 614 615 616 617 618
    }
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
    tcg_gen_br(l3);
    gen_set_label(l1);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
    tcg_gen_br(l3);
    gen_set_label(l2);
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
    gen_set_label(l3);
}

Blue Swirl's avatar
Blue Swirl committed
619
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
620
{
621 622 623
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp(arg0, t0, s, crf);
    tcg_temp_free(t0);
624 625 626
}

#if defined(TARGET_PPC64)
Blue Swirl's avatar
Blue Swirl committed
627
static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
628
{
629
    TCGv t0, t1;
pbrook's avatar
pbrook committed
630 631
    t0 = tcg_temp_local_new();
    t1 = tcg_temp_local_new();
632
    if (s) {
633 634
        tcg_gen_ext32s_tl(t0, arg0);
        tcg_gen_ext32s_tl(t1, arg1);
635
    } else {
636 637
        tcg_gen_ext32u_tl(t0, arg0);
        tcg_gen_ext32u_tl(t1, arg1);
638
    }
639 640 641
    gen_op_cmp(t0, t1, s, crf);
    tcg_temp_free(t1);
    tcg_temp_free(t0);
642 643
}

Blue Swirl's avatar
Blue Swirl committed
644
static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
645
{
646 647 648
    TCGv t0 = tcg_const_local_tl(arg1);
    gen_op_cmp32(arg0, t0, s, crf);
    tcg_temp_free(t0);
649 650 651
}
#endif

Blue Swirl's avatar
Blue Swirl committed
652
static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
653 654 655 656 657 658 659 660 661 662
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode))
        gen_op_cmpi32(reg, 0, 1, 0);
    else
#endif
        gen_op_cmpi(reg, 0, 1, 0);
}

/* cmp */
Blue Swirl's avatar
Blue Swirl committed
663
static void gen_cmp(DisasContext *ctx)
664 665 666 667 668 669 670 671 672 673 674 675
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     1, crfD(ctx->opcode));
    else
#endif
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   1, crfD(ctx->opcode));
}

/* cmpi */
Blue Swirl's avatar
Blue Swirl committed
676
static void gen_cmpi(DisasContext *ctx)
677 678 679 680 681 682 683 684 685 686 687 688
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                      1, crfD(ctx->opcode));
    else
#endif
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                    1, crfD(ctx->opcode));
}

/* cmpl */
Blue Swirl's avatar
Blue Swirl committed
689
static void gen_cmpl(DisasContext *ctx)
690 691 692 693 694 695 696 697 698 699 700 701
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                     0, crfD(ctx->opcode));
    else
#endif
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                   0, crfD(ctx->opcode));
}

/* cmpli */
Blue Swirl's avatar
Blue Swirl committed
702
static void gen_cmpli(DisasContext *ctx)
703 704 705 706 707 708 709 710 711 712 713 714
{
#if defined(TARGET_PPC64)
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                      0, crfD(ctx->opcode));
    else
#endif
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                    0, crfD(ctx->opcode));
}

/* isel (PowerPC 2.03 specification) */
Blue Swirl's avatar
Blue Swirl committed
715
static void gen_isel(DisasContext *ctx)
716 717 718 719
{
    int l1, l2;
    uint32_t bi = rC(ctx->opcode);
    uint32_t mask;
pbrook's avatar
pbrook committed
720
    TCGv_i32 t0;
721 722 723 724 725

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

    mask = 1 << (3 - (bi & 0x03));
pbrook's avatar
pbrook committed
726
    t0 = tcg_temp_new_i32();
727 728
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
729 730 731 732 733 734 735 736
    if (rA(ctx->opcode) == 0)
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
    else
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
    gen_set_label(l2);
pbrook's avatar
pbrook committed
737
    tcg_temp_free_i32(t0);
738 739
}

bellard's avatar
bellard committed
740 741
/***                           Integer arithmetic                          ***/

Blue Swirl's avatar
Blue Swirl committed
742 743
static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
                                           TCGv arg1, TCGv arg2, int sub)
744 745 746
{
    int l1;
    TCGv t0;
bellard's avatar
bellard committed
747

748 749 750
    l1 = gen_new_label();
    /* Start with XER OV disabled, the most likely case */
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
pbrook's avatar
pbrook committed
751
    t0 = tcg_temp_local_new();
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
    tcg_gen_xor_tl(t0, arg0, arg1);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    tcg_gen_xor_tl(t0, arg1, arg2);
#if defined(TARGET_PPC64)
    if (!ctx->sf_mode)
        tcg_gen_ext32s_tl(t0, t0);
#endif
    if (sub)
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
    else
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
    gen_set_label(l1);
    tcg_temp_free(t0);
bellard's avatar
bellard committed
773 774
}

Blue Swirl's avatar
Blue Swirl committed
775 776
static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1,
                                           TCGv arg2, int sub)
777 778
{
    int l1 = gen_new_label();
779 780

#if defined(TARGET_PPC64)
781 782
    if (!(ctx->sf_mode)) {
        TCGv t0, t1;
pbrook's avatar
pbrook committed
783 784
        t0 = tcg_temp_new();
        t1 = tcg_temp_new();
785

786 787 788 789
        tcg_gen_ext32u_tl(t0, arg1);
        tcg_gen_ext32u_tl(t1, arg2);
        if (sub) {
            tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
aurel32's avatar
aurel32 committed
790
        } else {
791 792
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
        }
793 794 795 796
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
        gen_set_label(l1);
        tcg_temp_free(t0);
        tcg_temp_free(t1);
797 798
    } else
#endif
799 800 801 802 803 804 805 806
    {
        if (sub) {
            tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
        } else {
            tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
        }
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
        gen_set_label(l1);
807
    }
808 809
}

810
/* Common add function */
Blue Swirl's avatar
Blue Swirl committed
811 812 813
static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                    TCGv arg2, int add_ca, int compute_ca,
                                    int compute_ov)
814 815
{
    TCGv t0, t1;
816

817
    if ((!compute_ca && !compute_ov) ||
pbrook's avatar
pbrook committed
818
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
819 820
        t0 = ret;
    } else {
pbrook's avatar
pbrook committed
821
        t0 = tcg_temp_local_new();
822
    }
bellard's avatar
bellard committed
823

824
    if (add_ca) {
pbrook's avatar
pbrook committed
825
        t1 = tcg_temp_local_new();
826 827
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
        tcg_gen_shri_tl(t1, t1, XER_CA);
828 829
    } else {
        TCGV_UNUSED(t1);
830
    }
bellard's avatar
bellard committed
831

832 833 834 835 836 837 838 839 840 841
    if (compute_ca && compute_ov) {
        /* Start with XER CA and OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
    } else if (compute_ca) {
        /* Start with XER CA disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
    } else if (compute_ov) {
        /* Start with XER OV disabled, the most likely case */
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
    }
bellard's avatar
bellard committed
842

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
    tcg_gen_add_tl(t0, arg1, arg2);

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

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

pbrook's avatar
pbrook committed
860
    if (!TCGV_EQUAL(t0, ret)) {
861 862 863
        tcg_gen_mov_tl(ret, t0);
        tcg_temp_free(t0);
    }
aurel32's avatar
aurel32 committed
864
}
865 866
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
Blue Swirl's avatar
Blue Swirl committed
867
static void glue(gen_, name)(DisasContext *ctx)                                       \
868 869 870 871 872 873 874 875
{                                                                             \
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
                     add_ca, compute_ca, compute_ov);                         \
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
                                add_ca, compute_ca, compute_ov)               \
Blue Swirl's avatar