Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ 18b21a2f

History | View | Annotate | Download (334.8 kB)

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

    
25
#include "cpu.h"
26
#include "exec-all.h"
27
#include "disas.h"
28
#include "tcg-op.h"
29
#include "qemu-common.h"
30
#include "host-utils.h"
31

    
32
#include "helper.h"
33
#define GEN_HELPER 1
34
#include "helper.h"
35

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

    
40
/* Include definitions for instructions classes and implementations flags */
41
//#define PPC_DEBUG_DISAS
42
//#define DO_PPC_STATISTICS
43

    
44
#ifdef PPC_DEBUG_DISAS
45
#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
46
#else
47
#  define LOG_DISAS(...) do { } while (0)
48
#endif
49
/*****************************************************************************/
50
/* Code translation helpers                                                  */
51

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

    
77
#include "gen-icount.h"
78

    
79
void ppc_translate_init(void)
80
{
81
    int i;
82
    char* p;
83
    size_t cpu_reg_names_size;
84
    static int done_init = 0;
85

    
86
    if (done_init)
87
        return;
88

    
89
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
90

    
91
    p = cpu_reg_names;
92
    cpu_reg_names_size = sizeof(cpu_reg_names);
93

    
94
    for (i = 0; i < 8; i++) {
95
        snprintf(p, cpu_reg_names_size, "crf%d", i);
96
        cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
97
                                            offsetof(CPUState, crf[i]), p);
98
        p += 5;
99
        cpu_reg_names_size -= 5;
100
    }
101

    
102
    for (i = 0; i < 32; i++) {
103
        snprintf(p, cpu_reg_names_size, "r%d", i);
104
        cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
105
                                        offsetof(CPUState, gpr[i]), p);
106
        p += (i < 10) ? 3 : 4;
107
        cpu_reg_names_size -= (i < 10) ? 3 : 4;
108
#if !defined(TARGET_PPC64)
109
        snprintf(p, cpu_reg_names_size, "r%dH", i);
110
        cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
111
                                             offsetof(CPUState, gprh[i]), p);
112
        p += (i < 10) ? 4 : 5;
113
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
114
#endif
115

    
116
        snprintf(p, cpu_reg_names_size, "fp%d", i);
117
        cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
118
                                            offsetof(CPUState, fpr[i]), p);
119
        p += (i < 10) ? 4 : 5;
120
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
121

    
122
        snprintf(p, cpu_reg_names_size, "avr%dH", i);
123
#ifdef HOST_WORDS_BIGENDIAN
124
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
125
                                             offsetof(CPUState, avr[i].u64[0]), p);
126
#else
127
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
128
                                             offsetof(CPUState, avr[i].u64[1]), p);
129
#endif
130
        p += (i < 10) ? 6 : 7;
131
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
132

    
133
        snprintf(p, cpu_reg_names_size, "avr%dL", i);
134
#ifdef HOST_WORDS_BIGENDIAN
135
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
136
                                             offsetof(CPUState, avr[i].u64[1]), p);
137
#else
138
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
139
                                             offsetof(CPUState, avr[i].u64[0]), p);
140
#endif
141
        p += (i < 10) ? 6 : 7;
142
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
143
    }
144

    
145
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
146
                                 offsetof(CPUState, nip), "nip");
147

    
148
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
149
                                 offsetof(CPUState, msr), "msr");
150

    
151
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
152
                                 offsetof(CPUState, ctr), "ctr");
153

    
154
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
155
                                offsetof(CPUState, lr), "lr");
156

    
157
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
158
                                 offsetof(CPUState, xer), "xer");
159

    
160
    cpu_reserve = tcg_global_mem_new(TCG_AREG0,
161
                                     offsetof(CPUState, reserve_addr),
162
                                     "reserve_addr");
163

    
164
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
165
                                       offsetof(CPUState, fpscr), "fpscr");
166

    
167
    cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
168
                                             offsetof(CPUState, access_type), "access_type");
169

    
170
    /* register helpers */
171
#define GEN_HELPER 2
172
#include "helper.h"
173

    
174
    done_init = 1;
175
}
176

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

    
198
struct opc_handler_t {
199
    /* invalid bits */
200
    uint32_t inval;
201
    /* instruction type */
202
    uint64_t type;
203
    /* handler */
204
    void (*handler)(DisasContext *ctx);
205
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
206
    const char *oname;
207
#endif
208
#if defined(DO_PPC_STATISTICS)
209
    uint64_t count;
210
#endif
211
};
212

    
213
static always_inline void gen_reset_fpstatus (void)
214
{
215
#ifdef CONFIG_SOFTFLOAT
216
    gen_helper_reset_fpstatus();
217
#endif
218
}
219

    
220
static always_inline void gen_compute_fprf (TCGv_i64 arg, int set_fprf, int set_rc)
221
{
222
    TCGv_i32 t0 = tcg_temp_new_i32();
223

    
224
    if (set_fprf != 0) {
225
        /* This case might be optimized later */
226
        tcg_gen_movi_i32(t0, 1);
227
        gen_helper_compute_fprf(t0, arg, t0);
228
        if (unlikely(set_rc)) {
229
            tcg_gen_mov_i32(cpu_crf[1], t0);
230
        }
231
        gen_helper_float_check_status();
232
    } else if (unlikely(set_rc)) {
233
        /* We always need to compute fpcc */
234
        tcg_gen_movi_i32(t0, 0);
235
        gen_helper_compute_fprf(t0, arg, t0);
236
        tcg_gen_mov_i32(cpu_crf[1], t0);
237
    }
238

    
239
    tcg_temp_free_i32(t0);
240
}
241

    
242
static always_inline void gen_set_access_type (DisasContext *ctx, int access_type)
243
{
244
    if (ctx->access_type != access_type) {
245
        tcg_gen_movi_i32(cpu_access_type, access_type);
246
        ctx->access_type = access_type;
247
    }
248
}
249

    
250
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
251
{
252
#if defined(TARGET_PPC64)
253
    if (ctx->sf_mode)
254
        tcg_gen_movi_tl(cpu_nip, nip);
255
    else
256
#endif
257
        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
258
}
259

    
260
static always_inline void gen_exception_err (DisasContext *ctx, uint32_t excp, uint32_t error)
261
{
262
    TCGv_i32 t0, t1;
263
    if (ctx->exception == POWERPC_EXCP_NONE) {
264
        gen_update_nip(ctx, ctx->nip);
265
    }
266
    t0 = tcg_const_i32(excp);
267
    t1 = tcg_const_i32(error);
268
    gen_helper_raise_exception_err(t0, t1);
269
    tcg_temp_free_i32(t0);
270
    tcg_temp_free_i32(t1);
271
    ctx->exception = (excp);
272
}
273

    
274
static always_inline void gen_exception (DisasContext *ctx, uint32_t excp)
275
{
276
    TCGv_i32 t0;
277
    if (ctx->exception == POWERPC_EXCP_NONE) {
278
        gen_update_nip(ctx, ctx->nip);
279
    }
280
    t0 = tcg_const_i32(excp);
281
    gen_helper_raise_exception(t0);
282
    tcg_temp_free_i32(t0);
283
    ctx->exception = (excp);
284
}
285

    
286
static always_inline void gen_debug_exception (DisasContext *ctx)
287
{
288
    TCGv_i32 t0;
289

    
290
    if (ctx->exception != POWERPC_EXCP_BRANCH)
291
        gen_update_nip(ctx, ctx->nip);
292
    t0 = tcg_const_i32(EXCP_DEBUG);
293
    gen_helper_raise_exception(t0);
294
    tcg_temp_free_i32(t0);
295
}
296

    
297
static always_inline void gen_inval_exception (DisasContext *ctx, uint32_t error)
298
{
299
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
300
}
301

    
302
/* Stop translation */
303
static always_inline void gen_stop_exception (DisasContext *ctx)
304
{
305
    gen_update_nip(ctx, ctx->nip);
306
    ctx->exception = POWERPC_EXCP_STOP;
307
}
308

    
309
/* No need to update nip here, as execution flow will change */
310
static always_inline void gen_sync_exception (DisasContext *ctx)
311
{
312
    ctx->exception = POWERPC_EXCP_SYNC;
313
}
314

    
315
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
316
GEN_OPCODE(name, opc1, opc2, opc3, inval, type)
317

    
318
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
319
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type)
320

    
321
typedef struct opcode_t {
322
    unsigned char opc1, opc2, opc3;
323
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
324
    unsigned char pad[5];
325
#else
326
    unsigned char pad[1];
327
#endif
328
    opc_handler_t handler;
329
    const char *oname;
330
} opcode_t;
331

    
332
/*****************************************************************************/
333
/***                           Instruction decoding                        ***/
334
#define EXTRACT_HELPER(name, shift, nb)                                       \
335
static always_inline uint32_t name (uint32_t opcode)                          \
336
{                                                                             \
337
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
338
}
339

    
340
#define EXTRACT_SHELPER(name, shift, nb)                                      \
341
static always_inline int32_t name (uint32_t opcode)                           \
342
{                                                                             \
343
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
344
}
345

    
346
/* Opcode part 1 */
347
EXTRACT_HELPER(opc1, 26, 6);
348
/* Opcode part 2 */
349
EXTRACT_HELPER(opc2, 1, 5);
350
/* Opcode part 3 */
351
EXTRACT_HELPER(opc3, 6, 5);
352
/* Update Cr0 flags */
353
EXTRACT_HELPER(Rc, 0, 1);
354
/* Destination */
355
EXTRACT_HELPER(rD, 21, 5);
356
/* Source */
357
EXTRACT_HELPER(rS, 21, 5);
358
/* First operand */
359
EXTRACT_HELPER(rA, 16, 5);
360
/* Second operand */
361
EXTRACT_HELPER(rB, 11, 5);
362
/* Third operand */
363
EXTRACT_HELPER(rC, 6, 5);
364
/***                               Get CRn                                 ***/
365
EXTRACT_HELPER(crfD, 23, 3);
366
EXTRACT_HELPER(crfS, 18, 3);
367
EXTRACT_HELPER(crbD, 21, 5);
368
EXTRACT_HELPER(crbA, 16, 5);
369
EXTRACT_HELPER(crbB, 11, 5);
370
/* SPR / TBL */
371
EXTRACT_HELPER(_SPR, 11, 10);
372
static always_inline uint32_t SPR (uint32_t opcode)
373
{
374
    uint32_t sprn = _SPR(opcode);
375

    
376
    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
377
}
378
/***                              Get constants                            ***/
379
EXTRACT_HELPER(IMM, 12, 8);
380
/* 16 bits signed immediate value */
381
EXTRACT_SHELPER(SIMM, 0, 16);
382
/* 16 bits unsigned immediate value */
383
EXTRACT_HELPER(UIMM, 0, 16);
384
/* 5 bits signed immediate value */
385
EXTRACT_HELPER(SIMM5, 16, 5);
386
/* 5 bits signed immediate value */
387
EXTRACT_HELPER(UIMM5, 16, 5);
388
/* Bit count */
389
EXTRACT_HELPER(NB, 11, 5);
390
/* Shift count */
391
EXTRACT_HELPER(SH, 11, 5);
392
/* Vector shift count */
393
EXTRACT_HELPER(VSH, 6, 4);
394
/* Mask start */
395
EXTRACT_HELPER(MB, 6, 5);
396
/* Mask end */
397
EXTRACT_HELPER(ME, 1, 5);
398
/* Trap operand */
399
EXTRACT_HELPER(TO, 21, 5);
400

    
401
EXTRACT_HELPER(CRM, 12, 8);
402
EXTRACT_HELPER(FM, 17, 8);
403
EXTRACT_HELPER(SR, 16, 4);
404
EXTRACT_HELPER(FPIMM, 12, 4);
405

    
406
/***                            Jump target decoding                       ***/
407
/* Displacement */
408
EXTRACT_SHELPER(d, 0, 16);
409
/* Immediate address */
410
static always_inline target_ulong LI (uint32_t opcode)
411
{
412
    return (opcode >> 0) & 0x03FFFFFC;
413
}
414

    
415
static always_inline uint32_t BD (uint32_t opcode)
416
{
417
    return (opcode >> 0) & 0xFFFC;
418
}
419

    
420
EXTRACT_HELPER(BO, 21, 5);
421
EXTRACT_HELPER(BI, 16, 5);
422
/* Absolute/relative address */
423
EXTRACT_HELPER(AA, 1, 1);
424
/* Link */
425
EXTRACT_HELPER(LK, 0, 1);
426

    
427
/* Create a mask between <start> and <end> bits */
428
static always_inline target_ulong MASK (uint32_t start, uint32_t end)
429
{
430
    target_ulong ret;
431

    
432
#if defined(TARGET_PPC64)
433
    if (likely(start == 0)) {
434
        ret = UINT64_MAX << (63 - end);
435
    } else if (likely(end == 63)) {
436
        ret = UINT64_MAX >> start;
437
    }
438
#else
439
    if (likely(start == 0)) {
440
        ret = UINT32_MAX << (31  - end);
441
    } else if (likely(end == 31)) {
442
        ret = UINT32_MAX >> start;
443
    }
444
#endif
445
    else {
446
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
447
            (((target_ulong)(-1ULL) >> (end)) >> 1);
448
        if (unlikely(start > end))
449
            return ~ret;
450
    }
451

    
452
    return ret;
453
}
454

    
455
/*****************************************************************************/
456
/* PowerPC instructions table                                                */
457

    
458
#if defined(DO_PPC_STATISTICS)
459
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
460
{                                                                             \
461
    .opc1 = op1,                                                              \
462
    .opc2 = op2,                                                              \
463
    .opc3 = op3,                                                              \
464
    .pad  = { 0, },                                                           \
465
    .handler = {                                                              \
466
        .inval   = invl,                                                      \
467
        .type = _typ,                                                         \
468
        .handler = &gen_##name,                                               \
469
        .oname = stringify(name),                                             \
470
    },                                                                        \
471
    .oname = stringify(name),                                                 \
472
}
473
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
474
{                                                                             \
475
    .opc1 = op1,                                                              \
476
    .opc2 = op2,                                                              \
477
    .opc3 = op3,                                                              \
478
    .pad  = { 0, },                                                           \
479
    .handler = {                                                              \
480
        .inval   = invl,                                                      \
481
        .type = _typ,                                                         \
482
        .handler = &gen_##name,                                               \
483
        .oname = onam,                                                        \
484
    },                                                                        \
485
    .oname = onam,                                                            \
486
}
487
#else
488
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
489
{                                                                             \
490
    .opc1 = op1,                                                              \
491
    .opc2 = op2,                                                              \
492
    .opc3 = op3,                                                              \
493
    .pad  = { 0, },                                                           \
494
    .handler = {                                                              \
495
        .inval   = invl,                                                      \
496
        .type = _typ,                                                         \
497
        .handler = &gen_##name,                                               \
498
    },                                                                        \
499
    .oname = stringify(name),                                                 \
500
}
501
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
502
{                                                                             \
503
    .opc1 = op1,                                                              \
504
    .opc2 = op2,                                                              \
505
    .opc3 = op3,                                                              \
506
    .pad  = { 0, },                                                           \
507
    .handler = {                                                              \
508
        .inval   = invl,                                                      \
509
        .type = _typ,                                                         \
510
        .handler = &gen_##name,                                               \
511
    },                                                                        \
512
    .oname = onam,                                                            \
513
}
514
#endif
515

    
516
/* SPR load/store helpers */
517
static always_inline void gen_load_spr(TCGv t, int reg)
518
{
519
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
520
}
521

    
522
static always_inline void gen_store_spr(int reg, TCGv t)
523
{
524
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
525
}
526

    
527
/* Invalid instruction */
528
static void gen_invalid(DisasContext *ctx)
529
{
530
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
531
}
532

    
533
static opc_handler_t invalid_handler = {
534
    .inval   = 0xFFFFFFFF,
535
    .type    = PPC_NONE,
536
    .handler = gen_invalid,
537
};
538

    
539
/***                           Integer comparison                          ***/
540

    
541
static always_inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
542
{
543
    int l1, l2, l3;
544

    
545
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
546
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
547
    tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);
548

    
549
    l1 = gen_new_label();
550
    l2 = gen_new_label();
551
    l3 = gen_new_label();
552
    if (s) {
553
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
554
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
555
    } else {
556
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
557
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
558
    }
559
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
560
    tcg_gen_br(l3);
561
    gen_set_label(l1);
562
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
563
    tcg_gen_br(l3);
564
    gen_set_label(l2);
565
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
566
    gen_set_label(l3);
567
}
568

    
569
static always_inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
570
{
571
    TCGv t0 = tcg_const_local_tl(arg1);
572
    gen_op_cmp(arg0, t0, s, crf);
573
    tcg_temp_free(t0);
574
}
575

    
576
#if defined(TARGET_PPC64)
577
static always_inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
578
{
579
    TCGv t0, t1;
580
    t0 = tcg_temp_local_new();
581
    t1 = tcg_temp_local_new();
582
    if (s) {
583
        tcg_gen_ext32s_tl(t0, arg0);
584
        tcg_gen_ext32s_tl(t1, arg1);
585
    } else {
586
        tcg_gen_ext32u_tl(t0, arg0);
587
        tcg_gen_ext32u_tl(t1, arg1);
588
    }
589
    gen_op_cmp(t0, t1, s, crf);
590
    tcg_temp_free(t1);
591
    tcg_temp_free(t0);
592
}
593

    
594
static always_inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
595
{
596
    TCGv t0 = tcg_const_local_tl(arg1);
597
    gen_op_cmp32(arg0, t0, s, crf);
598
    tcg_temp_free(t0);
599
}
600
#endif
601

    
602
static always_inline void gen_set_Rc0 (DisasContext *ctx, TCGv reg)
603
{
604
#if defined(TARGET_PPC64)
605
    if (!(ctx->sf_mode))
606
        gen_op_cmpi32(reg, 0, 1, 0);
607
    else
608
#endif
609
        gen_op_cmpi(reg, 0, 1, 0);
610
}
611

    
612
/* cmp */
613
static void gen_cmp(DisasContext *ctx)
614
{
615
#if defined(TARGET_PPC64)
616
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
617
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
618
                     1, crfD(ctx->opcode));
619
    else
620
#endif
621
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
622
                   1, crfD(ctx->opcode));
623
}
624

    
625
/* cmpi */
626
static void gen_cmpi(DisasContext *ctx)
627
{
628
#if defined(TARGET_PPC64)
629
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
630
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
631
                      1, crfD(ctx->opcode));
632
    else
633
#endif
634
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
635
                    1, crfD(ctx->opcode));
636
}
637

    
638
/* cmpl */
639
static void gen_cmpl(DisasContext *ctx)
640
{
641
#if defined(TARGET_PPC64)
642
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
643
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
644
                     0, crfD(ctx->opcode));
645
    else
646
#endif
647
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
648
                   0, crfD(ctx->opcode));
649
}
650

    
651
/* cmpli */
652
static void gen_cmpli(DisasContext *ctx)
653
{
654
#if defined(TARGET_PPC64)
655
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
656
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
657
                      0, crfD(ctx->opcode));
658
    else
659
#endif
660
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
661
                    0, crfD(ctx->opcode));
662
}
663

    
664
/* isel (PowerPC 2.03 specification) */
665
static void gen_isel(DisasContext *ctx)
666
{
667
    int l1, l2;
668
    uint32_t bi = rC(ctx->opcode);
669
    uint32_t mask;
670
    TCGv_i32 t0;
671

    
672
    l1 = gen_new_label();
673
    l2 = gen_new_label();
674

    
675
    mask = 1 << (3 - (bi & 0x03));
676
    t0 = tcg_temp_new_i32();
677
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
678
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
679
    if (rA(ctx->opcode) == 0)
680
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
681
    else
682
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
683
    tcg_gen_br(l2);
684
    gen_set_label(l1);
685
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
686
    gen_set_label(l2);
687
    tcg_temp_free_i32(t0);
688
}
689

    
690
/***                           Integer arithmetic                          ***/
691

    
692
static always_inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, TCGv arg1, TCGv arg2, int sub)
693
{
694
    int l1;
695
    TCGv t0;
696

    
697
    l1 = gen_new_label();
698
    /* Start with XER OV disabled, the most likely case */
699
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
700
    t0 = tcg_temp_local_new();
701
    tcg_gen_xor_tl(t0, arg0, arg1);
702
#if defined(TARGET_PPC64)
703
    if (!ctx->sf_mode)
704
        tcg_gen_ext32s_tl(t0, t0);
705
#endif
706
    if (sub)
707
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
708
    else
709
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
710
    tcg_gen_xor_tl(t0, arg1, arg2);
711
#if defined(TARGET_PPC64)
712
    if (!ctx->sf_mode)
713
        tcg_gen_ext32s_tl(t0, t0);
714
#endif
715
    if (sub)
716
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
717
    else
718
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
719
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
720
    gen_set_label(l1);
721
    tcg_temp_free(t0);
722
}
723

    
724
static always_inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, TCGv arg2, int sub)
725
{
726
    int l1 = gen_new_label();
727

    
728
#if defined(TARGET_PPC64)
729
    if (!(ctx->sf_mode)) {
730
        TCGv t0, t1;
731
        t0 = tcg_temp_new();
732
        t1 = tcg_temp_new();
733

    
734
        tcg_gen_ext32u_tl(t0, arg1);
735
        tcg_gen_ext32u_tl(t1, arg2);
736
        if (sub) {
737
            tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
738
        } else {
739
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
740
        }
741
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
742
        gen_set_label(l1);
743
        tcg_temp_free(t0);
744
        tcg_temp_free(t1);
745
    } else
746
#endif
747
    {
748
        if (sub) {
749
            tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
750
        } else {
751
            tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
752
        }
753
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
754
        gen_set_label(l1);
755
    }
756
}
757

    
758
/* Common add function */
759
static always_inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
760
                                           int add_ca, int compute_ca, int compute_ov)
761
{
762
    TCGv t0, t1;
763

    
764
    if ((!compute_ca && !compute_ov) ||
765
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
766
        t0 = ret;
767
    } else {
768
        t0 = tcg_temp_local_new();
769
    }
770

    
771
    if (add_ca) {
772
        t1 = tcg_temp_local_new();
773
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
774
        tcg_gen_shri_tl(t1, t1, XER_CA);
775
    } else {
776
        TCGV_UNUSED(t1);
777
    }
778

    
779
    if (compute_ca && compute_ov) {
780
        /* Start with XER CA and OV disabled, the most likely case */
781
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
782
    } else if (compute_ca) {
783
        /* Start with XER CA disabled, the most likely case */
784
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
785
    } else if (compute_ov) {
786
        /* Start with XER OV disabled, the most likely case */
787
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
788
    }
789

    
790
    tcg_gen_add_tl(t0, arg1, arg2);
791

    
792
    if (compute_ca) {
793
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
794
    }
795
    if (add_ca) {
796
        tcg_gen_add_tl(t0, t0, t1);
797
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
798
        tcg_temp_free(t1);
799
    }
800
    if (compute_ov) {
801
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
802
    }
803

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

    
807
    if (!TCGV_EQUAL(t0, ret)) {
808
        tcg_gen_mov_tl(ret, t0);
809
        tcg_temp_free(t0);
810
    }
811
}
812
/* Add functions with two operands */
813
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
814
static void glue(gen_, name)(DisasContext *ctx)                                       \
815
{                                                                             \
816
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
817
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
818
                     add_ca, compute_ca, compute_ov);                         \
819
}
820
/* Add functions with one operand and one immediate */
821
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
822
                                add_ca, compute_ca, compute_ov)               \
823
static void glue(gen_, name)(DisasContext *ctx)                                       \
824
{                                                                             \
825
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
826
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
827
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
828
                     add_ca, compute_ca, compute_ov);                         \
829
    tcg_temp_free(t0);                                                        \
830
}
831

    
832
/* add  add.  addo  addo. */
833
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
834
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
835
/* addc  addc.  addco  addco. */
836
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
837
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
838
/* adde  adde.  addeo  addeo. */
839
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
840
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
841
/* addme  addme.  addmeo  addmeo.  */
842
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
843
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
844
/* addze  addze.  addzeo  addzeo.*/
845
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
846
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
847
/* addi */
848
static void gen_addi(DisasContext *ctx)
849
{
850
    target_long simm = SIMM(ctx->opcode);
851

    
852
    if (rA(ctx->opcode) == 0) {
853
        /* li case */
854
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
855
    } else {
856
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
857
    }
858
}
859
/* addic  addic.*/
860
static always_inline void gen_op_addic (DisasContext *ctx, TCGv ret, TCGv arg1,
861
                                        int compute_Rc0)
862
{
863
    target_long simm = SIMM(ctx->opcode);
864

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

    
868
    if (likely(simm != 0)) {
869
        TCGv t0 = tcg_temp_local_new();
870
        tcg_gen_addi_tl(t0, arg1, simm);
871
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
872
        tcg_gen_mov_tl(ret, t0);
873
        tcg_temp_free(t0);
874
    } else {
875
        tcg_gen_mov_tl(ret, arg1);
876
    }
877
    if (compute_Rc0) {
878
        gen_set_Rc0(ctx, ret);
879
    }
880
}
881

    
882
static void gen_addic(DisasContext *ctx)
883
{
884
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
885
}
886

    
887
static void gen_addic_(DisasContext *ctx)
888
{
889
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
890
}
891

    
892
/* addis */
893
static void gen_addis(DisasContext *ctx)
894
{
895
    target_long simm = SIMM(ctx->opcode);
896

    
897
    if (rA(ctx->opcode) == 0) {
898
        /* lis case */
899
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
900
    } else {
901
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
902
    }
903
}
904

    
905
static always_inline void gen_op_arith_divw (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
906
                                             int sign, int compute_ov)
907
{
908
    int l1 = gen_new_label();
909
    int l2 = gen_new_label();
910
    TCGv_i32 t0 = tcg_temp_local_new_i32();
911
    TCGv_i32 t1 = tcg_temp_local_new_i32();
912

    
913
    tcg_gen_trunc_tl_i32(t0, arg1);
914
    tcg_gen_trunc_tl_i32(t1, arg2);
915
    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
916
    if (sign) {
917
        int l3 = gen_new_label();
918
        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
919
        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
920
        gen_set_label(l3);
921
        tcg_gen_div_i32(t0, t0, t1);
922
    } else {
923
        tcg_gen_divu_i32(t0, t0, t1);
924
    }
925
    if (compute_ov) {
926
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
927
    }
928
    tcg_gen_br(l2);
929
    gen_set_label(l1);
930
    if (sign) {
931
        tcg_gen_sari_i32(t0, t0, 31);
932
    } else {
933
        tcg_gen_movi_i32(t0, 0);
934
    }
935
    if (compute_ov) {
936
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
937
    }
938
    gen_set_label(l2);
939
    tcg_gen_extu_i32_tl(ret, t0);
940
    tcg_temp_free_i32(t0);
941
    tcg_temp_free_i32(t1);
942
    if (unlikely(Rc(ctx->opcode) != 0))
943
        gen_set_Rc0(ctx, ret);
944
}
945
/* Div functions */
946
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
947
static void glue(gen_, name)(DisasContext *ctx)                                       \
948
{                                                                             \
949
    gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)],                          \
950
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
951
                     sign, compute_ov);                                       \
952
}
953
/* divwu  divwu.  divwuo  divwuo.   */
954
GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
955
GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
956
/* divw  divw.  divwo  divwo.   */
957
GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
958
GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
959
#if defined(TARGET_PPC64)
960
static always_inline void gen_op_arith_divd (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
961
                                             int sign, int compute_ov)
962
{
963
    int l1 = gen_new_label();
964
    int l2 = gen_new_label();
965

    
966
    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
967
    if (sign) {
968
        int l3 = gen_new_label();
969
        tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
970
        tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
971
        gen_set_label(l3);
972
        tcg_gen_div_i64(ret, arg1, arg2);
973
    } else {
974
        tcg_gen_divu_i64(ret, arg1, arg2);
975
    }
976
    if (compute_ov) {
977
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
978
    }
979
    tcg_gen_br(l2);
980
    gen_set_label(l1);
981
    if (sign) {
982
        tcg_gen_sari_i64(ret, arg1, 63);
983
    } else {
984
        tcg_gen_movi_i64(ret, 0);
985
    }
986
    if (compute_ov) {
987
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
988
    }
989
    gen_set_label(l2);
990
    if (unlikely(Rc(ctx->opcode) != 0))
991
        gen_set_Rc0(ctx, ret);
992
}
993
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
994
static void glue(gen_, name)(DisasContext *ctx)                                       \
995
{                                                                             \
996
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
997
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
998
                      sign, compute_ov);                                      \
999
}
1000
/* divwu  divwu.  divwuo  divwuo.   */
1001
GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1002
GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1003
/* divw  divw.  divwo  divwo.   */
1004
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1005
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1006
#endif
1007

    
1008
/* mulhw  mulhw. */
1009
static void gen_mulhw(DisasContext *ctx)
1010
{
1011
    TCGv_i64 t0, t1;
1012

    
1013
    t0 = tcg_temp_new_i64();
1014
    t1 = tcg_temp_new_i64();
1015
#if defined(TARGET_PPC64)
1016
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1017
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1018
    tcg_gen_mul_i64(t0, t0, t1);
1019
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1020
#else
1021
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1022
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1023
    tcg_gen_mul_i64(t0, t0, t1);
1024
    tcg_gen_shri_i64(t0, t0, 32);
1025
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1026
#endif
1027
    tcg_temp_free_i64(t0);
1028
    tcg_temp_free_i64(t1);
1029
    if (unlikely(Rc(ctx->opcode) != 0))
1030
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1031
}
1032

    
1033
/* mulhwu  mulhwu.  */
1034
static void gen_mulhwu(DisasContext *ctx)
1035
{
1036
    TCGv_i64 t0, t1;
1037

    
1038
    t0 = tcg_temp_new_i64();
1039
    t1 = tcg_temp_new_i64();
1040
#if defined(TARGET_PPC64)
1041
    tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1042
    tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1043
    tcg_gen_mul_i64(t0, t0, t1);
1044
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1045
#else
1046
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1047
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1048
    tcg_gen_mul_i64(t0, t0, t1);
1049
    tcg_gen_shri_i64(t0, t0, 32);
1050
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1051
#endif
1052
    tcg_temp_free_i64(t0);
1053
    tcg_temp_free_i64(t1);
1054
    if (unlikely(Rc(ctx->opcode) != 0))
1055
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1056
}
1057

    
1058
/* mullw  mullw. */
1059
static void gen_mullw(DisasContext *ctx)
1060
{
1061
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1062
                   cpu_gpr[rB(ctx->opcode)]);
1063
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1064
    if (unlikely(Rc(ctx->opcode) != 0))
1065
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1066
}
1067

    
1068
/* mullwo  mullwo. */
1069
static void gen_mullwo(DisasContext *ctx)
1070
{
1071
    int l1;
1072
    TCGv_i64 t0, t1;
1073

    
1074
    t0 = tcg_temp_new_i64();
1075
    t1 = tcg_temp_new_i64();
1076
    l1 = gen_new_label();
1077
    /* Start with XER OV disabled, the most likely case */
1078
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1079
#if defined(TARGET_PPC64)
1080
    tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1081
    tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1082
#else
1083
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1084
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1085
#endif
1086
    tcg_gen_mul_i64(t0, t0, t1);
1087
#if defined(TARGET_PPC64)
1088
    tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
1089
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
1090
#else
1091
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1092
    tcg_gen_ext32s_i64(t1, t0);
1093
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
1094
#endif
1095
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1096
    gen_set_label(l1);
1097
    tcg_temp_free_i64(t0);
1098
    tcg_temp_free_i64(t1);
1099
    if (unlikely(Rc(ctx->opcode) != 0))
1100
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1101
}
1102

    
1103
/* mulli */
1104
static void gen_mulli(DisasContext *ctx)
1105
{
1106
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1107
                    SIMM(ctx->opcode));
1108
}
1109
#if defined(TARGET_PPC64)
1110
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
1111
static void glue(gen_, name)(DisasContext *ctx)                                       \
1112
{                                                                             \
1113
    gen_helper_##name (cpu_gpr[rD(ctx->opcode)],                              \
1114
                       cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);   \
1115
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1116
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);                           \
1117
}
1118
/* mulhd  mulhd. */
1119
GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
1120
/* mulhdu  mulhdu. */
1121
GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
1122

    
1123
/* mulld  mulld. */
1124
static void gen_mulld(DisasContext *ctx)
1125
{
1126
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1127
                   cpu_gpr[rB(ctx->opcode)]);
1128
    if (unlikely(Rc(ctx->opcode) != 0))
1129
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1130
}
1131
/* mulldo  mulldo. */
1132
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1133
#endif
1134

    
1135
/* neg neg. nego nego. */
1136
static always_inline void gen_op_arith_neg (DisasContext *ctx, TCGv ret, TCGv arg1, int ov_check)
1137
{
1138
    int l1 = gen_new_label();
1139
    int l2 = gen_new_label();
1140
    TCGv t0 = tcg_temp_local_new();
1141
#if defined(TARGET_PPC64)
1142
    if (ctx->sf_mode) {
1143
        tcg_gen_mov_tl(t0, arg1);
1144
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
1145
    } else
1146
#endif
1147
    {
1148
        tcg_gen_ext32s_tl(t0, arg1);
1149
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
1150
    }
1151
    tcg_gen_neg_tl(ret, arg1);
1152
    if (ov_check) {
1153
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1154
    }
1155
    tcg_gen_br(l2);
1156
    gen_set_label(l1);
1157
    tcg_gen_mov_tl(ret, t0);
1158
    if (ov_check) {
1159
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1160
    }
1161
    gen_set_label(l2);
1162
    tcg_temp_free(t0);
1163
    if (unlikely(Rc(ctx->opcode) != 0))
1164
        gen_set_Rc0(ctx, ret);
1165
}
1166

    
1167
static void gen_neg(DisasContext *ctx)
1168
{
1169
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1170
}
1171

    
1172
static void gen_nego(DisasContext *ctx)
1173
{
1174
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1175
}
1176

    
1177
/* Common subf function */
1178
static always_inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
1179
                                            int add_ca, int compute_ca, int compute_ov)
1180
{
1181
    TCGv t0, t1;
1182

    
1183
    if ((!compute_ca && !compute_ov) ||
1184
        (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1185
        t0 = ret;
1186
    } else {
1187
        t0 = tcg_temp_local_new();
1188
    }
1189

    
1190
    if (add_ca) {
1191
        t1 = tcg_temp_local_new();
1192
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
1193
        tcg_gen_shri_tl(t1, t1, XER_CA);
1194
    } else {
1195
        TCGV_UNUSED(t1);
1196
    }
1197

    
1198
    if (compute_ca && compute_ov) {
1199
        /* Start with XER CA and OV disabled, the most likely case */
1200
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
1201
    } else if (compute_ca) {
1202
        /* Start with XER CA disabled, the most likely case */
1203
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1204
    } else if (compute_ov) {
1205
        /* Start with XER OV disabled, the most likely case */
1206
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1207
    }
1208

    
1209
    if (add_ca) {
1210
        tcg_gen_not_tl(t0, arg1);
1211
        tcg_gen_add_tl(t0, t0, arg2);
1212
        gen_op_arith_compute_ca(ctx, t0, arg2, 0);
1213
        tcg_gen_add_tl(t0, t0, t1);
1214
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
1215
        tcg_temp_free(t1);
1216
    } else {
1217
        tcg_gen_sub_tl(t0, arg2, arg1);
1218
        if (compute_ca) {
1219
            gen_op_arith_compute_ca(ctx, t0, arg2, 1);
1220
        }
1221
    }
1222
    if (compute_ov) {
1223
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1224
    }
1225

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

    
1229
    if (!TCGV_EQUAL(t0, ret)) {
1230
        tcg_gen_mov_tl(ret, t0);
1231
        tcg_temp_free(t0);
1232
    }
1233
}
1234
/* Sub functions with Two operands functions */
1235
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
1236
static void glue(gen_, name)(DisasContext *ctx)                                       \
1237
{                                                                             \
1238
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1239
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1240
                      add_ca, compute_ca, compute_ov);                        \
1241
}
1242
/* Sub functions with one operand and one immediate */
1243
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
1244
                                add_ca, compute_ca, compute_ov)               \
1245
static void glue(gen_, name)(DisasContext *ctx)                                       \
1246
{                                                                             \
1247
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
1248
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1249
                      cpu_gpr[rA(ctx->opcode)], t0,                           \
1250
                      add_ca, compute_ca, compute_ov);                        \
1251
    tcg_temp_free(t0);                                                        \
1252
}
1253
/* subf  subf.  subfo  subfo. */
1254
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1255
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1256
/* subfc  subfc.  subfco  subfco. */
1257
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1258
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1259
/* subfe  subfe.  subfeo  subfo. */
1260
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1261
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1262
/* subfme  subfme.  subfmeo  subfmeo.  */
1263
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1264
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1265
/* subfze  subfze.  subfzeo  subfzeo.*/
1266
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1267
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
1268

    
1269
/* subfic */
1270
static void gen_subfic(DisasContext *ctx)
1271
{
1272
    /* Start with XER CA and OV disabled, the most likely case */
1273
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1274
    TCGv t0 = tcg_temp_local_new();
1275
    TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
1276
    tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
1277
    gen_op_arith_compute_ca(ctx, t0, t1, 1);
1278
    tcg_temp_free(t1);
1279
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
1280
    tcg_temp_free(t0);
1281
}
1282

    
1283
/***                            Integer logical                            ***/
1284
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
1285
static void glue(gen_, name)(DisasContext *ctx)                                       \
1286
{                                                                             \
1287
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
1288
       cpu_gpr[rB(ctx->opcode)]);                                             \
1289
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1290
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1291
}
1292

    
1293
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
1294
static void glue(gen_, name)(DisasContext *ctx)                                       \
1295
{                                                                             \
1296
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1297
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1298
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1299
}
1300

    
1301
/* and & and. */
1302
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
1303
/* andc & andc. */
1304
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
1305

    
1306
/* andi. */
1307
static void gen_andi_(DisasContext *ctx)
1308
{
1309
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1310
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1311
}
1312

    
1313
/* andis. */
1314
static void gen_andis_(DisasContext *ctx)
1315
{
1316
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1317
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1318
}
1319

    
1320
/* cntlzw */
1321
static void gen_cntlzw(DisasContext *ctx)
1322
{
1323
    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1324
    if (unlikely(Rc(ctx->opcode) != 0))
1325
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1326
}
1327
/* eqv & eqv. */
1328
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
1329
/* extsb & extsb. */
1330
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
1331
/* extsh & extsh. */
1332
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
1333
/* nand & nand. */
1334
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
1335
/* nor & nor. */
1336
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
1337

    
1338
/* or & or. */
1339
static void gen_or(DisasContext *ctx)
1340
{
1341
    int rs, ra, rb;
1342

    
1343
    rs = rS(ctx->opcode);
1344
    ra = rA(ctx->opcode);
1345
    rb = rB(ctx->opcode);
1346
    /* Optimisation for mr. ri case */
1347
    if (rs != ra || rs != rb) {
1348
        if (rs != rb)
1349
            tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1350
        else
1351
            tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
1352
        if (unlikely(Rc(ctx->opcode) != 0))
1353
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1354
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1355
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1356
#if defined(TARGET_PPC64)
1357
    } else {
1358
        int prio = 0;
1359

    
1360
        switch (rs) {
1361
        case 1:
1362
            /* Set process priority to low */
1363
            prio = 2;
1364
            break;
1365
        case 6:
1366
            /* Set process priority to medium-low */
1367
            prio = 3;
1368
            break;
1369
        case 2:
1370
            /* Set process priority to normal */
1371
            prio = 4;
1372
            break;
1373
#if !defined(CONFIG_USER_ONLY)
1374
        case 31:
1375
            if (ctx->mem_idx > 0) {
1376
                /* Set process priority to very low */
1377
                prio = 1;
1378
            }
1379
            break;
1380
        case 5:
1381
            if (ctx->mem_idx > 0) {
1382
                /* Set process priority to medium-hight */
1383
                prio = 5;
1384
            }
1385
            break;
1386
        case 3:
1387
            if (ctx->mem_idx > 0) {
1388
                /* Set process priority to high */
1389
                prio = 6;
1390
            }
1391
            break;
1392
        case 7:
1393
            if (ctx->mem_idx > 1) {
1394
                /* Set process priority to very high */
1395
                prio = 7;
1396
            }
1397
            break;
1398
#endif
1399
        default:
1400
            /* nop */
1401
            break;
1402
        }
1403
        if (prio) {
1404
            TCGv t0 = tcg_temp_new();
1405
            gen_load_spr(t0, SPR_PPR);
1406
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1407
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1408
            gen_store_spr(SPR_PPR, t0);
1409
            tcg_temp_free(t0);
1410
        }
1411
#endif
1412
    }
1413
}
1414
/* orc & orc. */
1415
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
1416

    
1417
/* xor & xor. */
1418
static void gen_xor(DisasContext *ctx)
1419
{
1420
    /* Optimisation for "set to zero" case */
1421
    if (rS(ctx->opcode) != rB(ctx->opcode))
1422
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1423
    else
1424
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1425
    if (unlikely(Rc(ctx->opcode) != 0))
1426
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1427
}
1428

    
1429
/* ori */
1430
static void gen_ori(DisasContext *ctx)
1431
{
1432
    target_ulong uimm = UIMM(ctx->opcode);
1433

    
1434
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1435
        /* NOP */
1436
        /* XXX: should handle special NOPs for POWER series */
1437
        return;
1438
    }
1439
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1440
}
1441

    
1442
/* oris */
1443
static void gen_oris(DisasContext *ctx)
1444
{
1445
    target_ulong uimm = UIMM(ctx->opcode);
1446

    
1447
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1448
        /* NOP */
1449
        return;
1450
    }
1451
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1452
}
1453

    
1454
/* xori */
1455
static void gen_xori(DisasContext *ctx)
1456
{
1457
    target_ulong uimm = UIMM(ctx->opcode);
1458

    
1459
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1460
        /* NOP */
1461
        return;
1462
    }
1463
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1464
}
1465

    
1466
/* xoris */
1467
static void gen_xoris(DisasContext *ctx)
1468
{
1469
    target_ulong uimm = UIMM(ctx->opcode);
1470

    
1471
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1472
        /* NOP */
1473
        return;
1474
    }
1475
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1476
}
1477

    
1478
/* popcntb : PowerPC 2.03 specification */
1479
static void gen_popcntb(DisasContext *ctx)
1480
{
1481
#if defined(TARGET_PPC64)
1482
    if (ctx->sf_mode)
1483
        gen_helper_popcntb_64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1484
    else
1485
#endif
1486
        gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1487
}
1488

    
1489
#if defined(TARGET_PPC64)
1490
/* extsw & extsw. */
1491
GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1492

    
1493
/* cntlzd */
1494
static void gen_cntlzd(DisasContext *ctx)
1495
{
1496
    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1497
    if (unlikely(Rc(ctx->opcode) != 0))
1498
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1499
}
1500
#endif
1501

    
1502
/***                             Integer rotate                            ***/
1503

    
1504
/* rlwimi & rlwimi. */
1505
static void gen_rlwimi(DisasContext *ctx)
1506
{
1507
    uint32_t mb, me, sh;
1508

    
1509
    mb = MB(ctx->opcode);
1510
    me = ME(ctx->opcode);
1511
    sh = SH(ctx->opcode);
1512
    if (likely(sh == 0 && mb == 0 && me == 31)) {
1513
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1514
    } else {
1515
        target_ulong mask;
1516
        TCGv t1;
1517
        TCGv t0 = tcg_temp_new();
1518
#if defined(TARGET_PPC64)
1519
        TCGv_i32 t2 = tcg_temp_new_i32();
1520
        tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
1521
        tcg_gen_rotli_i32(t2, t2, sh);
1522
        tcg_gen_extu_i32_i64(t0, t2);
1523
        tcg_temp_free_i32(t2);
1524
#else
1525
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1526
#endif
1527
#if defined(TARGET_PPC64)
1528
        mb += 32;
1529
        me += 32;
1530
#endif
1531
        mask = MASK(mb, me);
1532
        t1 = tcg_temp_new();
1533
        tcg_gen_andi_tl(t0, t0, mask);
1534
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1535
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1536
        tcg_temp_free(t0);
1537
        tcg_temp_free(t1);
1538
    }
1539
    if (unlikely(Rc(ctx->opcode) != 0))
1540
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1541
}
1542

    
1543
/* rlwinm & rlwinm. */
1544
static void gen_rlwinm(DisasContext *ctx)
1545
{
1546
    uint32_t mb, me, sh;
1547

    
1548
    sh = SH(ctx->opcode);
1549
    mb = MB(ctx->opcode);
1550
    me = ME(ctx->opcode);
1551

    
1552
    if (likely(mb == 0 && me == (31 - sh))) {
1553
        if (likely(sh == 0)) {
1554
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1555
        } else {
1556
            TCGv t0 = tcg_temp_new();
1557
            tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1558
            tcg_gen_shli_tl(t0, t0, sh);
1559
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1560
            tcg_temp_free(t0);
1561
        }
1562
    } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
1563
        TCGv t0 = tcg_temp_new();
1564
        tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1565
        tcg_gen_shri_tl(t0, t0, mb);
1566
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1567
        tcg_temp_free(t0);
1568
    } else {
1569
        TCGv t0 = tcg_temp_new();
1570
#if defined(TARGET_PPC64)
1571
        TCGv_i32 t1 = tcg_temp_new_i32();
1572
        tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1573
        tcg_gen_rotli_i32(t1, t1, sh);
1574
        tcg_gen_extu_i32_i64(t0, t1);
1575
        tcg_temp_free_i32(t1);
1576
#else
1577
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1578
#endif
1579
#if defined(TARGET_PPC64)
1580
        mb += 32;
1581
        me += 32;
1582
#endif
1583
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1584
        tcg_temp_free(t0);
1585
    }
1586
    if (unlikely(Rc(ctx->opcode) != 0))
1587
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1588
}
1589

    
1590
/* rlwnm & rlwnm. */
1591
static void gen_rlwnm(DisasContext *ctx)
1592
{
1593
    uint32_t mb, me;
1594
    TCGv t0;
1595
#if defined(TARGET_PPC64)
1596
    TCGv_i32 t1, t2;
1597
#endif
1598

    
1599
    mb = MB(ctx->opcode);
1600
    me = ME(ctx->opcode);
1601
    t0 = tcg_temp_new();
1602
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1603
#if defined(TARGET_PPC64)
1604
    t1 = tcg_temp_new_i32();
1605
    t2 = tcg_temp_new_i32();
1606
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1607
    tcg_gen_trunc_i64_i32(t2, t0);
1608
    tcg_gen_rotl_i32(t1, t1, t2);
1609
    tcg_gen_extu_i32_i64(t0, t1);
1610
    tcg_temp_free_i32(t1);
1611
    tcg_temp_free_i32(t2);
1612
#else
1613
    tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
1614
#endif
1615
    if (unlikely(mb != 0 || me != 31)) {
1616
#if defined(TARGET_PPC64)
1617
        mb += 32;
1618
        me += 32;
1619
#endif
1620
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1621
    } else {
1622
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1623
    }
1624
    tcg_temp_free(t0);
1625
    if (unlikely(Rc(ctx->opcode) != 0))
1626
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1627
}
1628

    
1629
#if defined(TARGET_PPC64)
1630
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
1631
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1632
{                                                                             \
1633
    gen_##name(ctx, 0);                                                       \
1634
}                                                                             \
1635
                                                                              \
1636
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1637
{                                                                             \
1638
    gen_##name(ctx, 1);                                                       \
1639
}
1640
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
1641
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1642
{                                                                             \
1643
    gen_##name(ctx, 0, 0);                                                    \
1644
}                                                                             \
1645
                                                                              \
1646
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1647
{                                                                             \
1648
    gen_##name(ctx, 0, 1);                                                    \
1649
}                                                                             \
1650
                                                                              \
1651
static void glue(gen_, name##2)(DisasContext *ctx)                            \
1652
{                                                                             \
1653
    gen_##name(ctx, 1, 0);                                                    \
1654
}                                                                             \
1655
                                                                              \
1656
static void glue(gen_, name##3)(DisasContext *ctx)                            \
1657
{                                                                             \
1658
    gen_##name(ctx, 1, 1);                                                    \
1659
}
1660

    
1661
static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
1662
                                      uint32_t me, uint32_t sh)
1663
{
1664
    if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
1665
        tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1666
    } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
1667
        tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
1668
    } else {
1669
        TCGv t0 = tcg_temp_new();
1670
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1671
        if (likely(mb == 0 && me == 63)) {
1672
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1673
        } else {
1674
            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1675
        }
1676
        tcg_temp_free(t0);
1677
    }
1678
    if (unlikely(Rc(ctx->opcode) != 0))
1679
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1680
}
1681
/* rldicl - rldicl. */
1682
static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1683
{
1684
    uint32_t sh, mb;
1685

    
1686
    sh = SH(ctx->opcode) | (shn << 5);
1687
    mb = MB(ctx->opcode) | (mbn << 5);
1688
    gen_rldinm(ctx, mb, 63, sh);
1689
}
1690
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1691
/* rldicr - rldicr. */
1692
static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1693
{
1694
    uint32_t sh, me;
1695

    
1696
    sh = SH(ctx->opcode) | (shn << 5);
1697
    me = MB(ctx->opcode) | (men << 5);
1698
    gen_rldinm(ctx, 0, me, sh);
1699
}
1700
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1701
/* rldic - rldic. */
1702
static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1703
{
1704
    uint32_t sh, mb;
1705

    
1706
    sh = SH(ctx->opcode) | (shn << 5);
1707
    mb = MB(ctx->opcode) | (mbn << 5);
1708
    gen_rldinm(ctx, mb, 63 - sh, sh);
1709
}
1710
GEN_PPC64_R4(rldic, 0x1E, 0x04);
1711

    
1712
static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
1713
                                     uint32_t me)
1714
{
1715
    TCGv t0;
1716

    
1717
    mb = MB(ctx->opcode);
1718
    me = ME(ctx->opcode);
1719
    t0 = tcg_temp_new();
1720
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1721
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1722
    if (unlikely(mb != 0 || me != 63)) {
1723
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1724
    } else {
1725
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1726
    }
1727
    tcg_temp_free(t0);
1728
    if (unlikely(Rc(ctx->opcode) != 0))
1729
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1730
}
1731

    
1732
/* rldcl - rldcl. */
1733
static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1734
{
1735
    uint32_t mb;
1736

    
1737
    mb = MB(ctx->opcode) | (mbn << 5);
1738
    gen_rldnm(ctx, mb, 63);
1739
}
1740
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1741
/* rldcr - rldcr. */
1742
static always_inline void gen_rldcr (DisasContext *ctx, int men)
1743
{
1744
    uint32_t me;
1745

    
1746
    me = MB(ctx->opcode) | (men << 5);
1747
    gen_rldnm(ctx, 0, me);
1748
}
1749
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1750
/* rldimi - rldimi. */
1751
static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1752
{
1753
    uint32_t sh, mb, me;
1754

    
1755
    sh = SH(ctx->opcode) | (shn << 5);
1756
    mb = MB(ctx->opcode) | (mbn << 5);
1757
    me = 63 - sh;
1758
    if (unlikely(sh == 0 && mb == 0)) {
1759
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1760
    } else {
1761
        TCGv t0, t1;
1762
        target_ulong mask;
1763

    
1764
        t0 = tcg_temp_new();
1765
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1766
        t1 = tcg_temp_new();
1767
        mask = MASK(mb, me);
1768
        tcg_gen_andi_tl(t0, t0, mask);
1769
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1770
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1771
        tcg_temp_free(t0);
1772
        tcg_temp_free(t1);
1773
    }
1774
    if (unlikely(Rc(ctx->opcode) != 0))
1775
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1776
}
1777
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1778
#endif
1779

    
1780
/***                             Integer shift                             ***/
1781

    
1782
/* slw & slw. */
1783
static void gen_slw(DisasContext *ctx)
1784
{
1785
    TCGv t0;
1786
    int l1, l2;
1787
    l1 = gen_new_label();
1788
    l2 = gen_new_label();
1789

    
1790
    t0 = tcg_temp_local_new();
1791
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1792
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
1793
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1794
    tcg_gen_br(l2);
1795
    gen_set_label(l1);
1796
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
1797
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1798
    gen_set_label(l2);
1799
    tcg_temp_free(t0);
1800
    if (unlikely(Rc(ctx->opcode) != 0))
1801
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1802
}
1803

    
1804
/* sraw & sraw. */
1805
static void gen_sraw(DisasContext *ctx)
1806
{
1807
    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)],
1808
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1809
    if (unlikely(Rc(ctx->opcode) != 0))
1810
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1811
}
1812

    
1813
/* srawi & srawi. */
1814
static void gen_srawi(DisasContext *ctx)
1815
{
1816
    int sh = SH(ctx->opcode);
1817
    if (sh != 0) {
1818
        int l1, l2;
1819
        TCGv t0;
1820
        l1 = gen_new_label();
1821
        l2 = gen_new_label();
1822
        t0 = tcg_temp_local_new();
1823
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1824
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
1825
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1826
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1827
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1828
        tcg_gen_br(l2);
1829
        gen_set_label(l1);
1830
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1831
        gen_set_label(l2);
1832
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1833
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
1834
        tcg_temp_free(t0);
1835
    } else {
1836
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1837
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1838
    }
1839
    if (unlikely(Rc(ctx->opcode) != 0))
1840
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1841
}
1842

    
1843
/* srw & srw. */
1844
static void gen_srw(DisasContext *ctx)
1845
{
1846
    TCGv t0, t1;
1847
    int l1, l2;
1848
    l1 = gen_new_label();
1849
    l2 = gen_new_label();
1850

    
1851
    t0 = tcg_temp_local_new();
1852
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1853
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
1854
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1855
    tcg_gen_br(l2);
1856
    gen_set_label(l1);
1857
    t1 = tcg_temp_new();
1858
    tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
1859
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t1, t0);
1860
    tcg_temp_free(t1);
1861
    gen_set_label(l2);
1862
    tcg_temp_free(t0);
1863
    if (unlikely(Rc(ctx->opcode) != 0))
1864
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1865
}
1866

    
1867
#if defined(TARGET_PPC64)
1868
/* sld & sld. */
1869
static void gen_sld(DisasContext *ctx)
1870
{
1871
    TCGv t0;
1872
    int l1, l2;
1873
    l1 = gen_new_label();
1874
    l2 = gen_new_label();
1875

    
1876
    t0 = tcg_temp_local_new();
1877
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
1878
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
1879
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1880
    tcg_gen_br(l2);
1881
    gen_set_label(l1);
1882
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
1883
    gen_set_label(l2);
1884
    tcg_temp_free(t0);
1885
    if (unlikely(Rc(ctx->opcode) != 0))
1886
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1887
}
1888

    
1889
/* srad & srad. */
1890
static void gen_srad(DisasContext *ctx)
1891
{
1892
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
1893
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1894
    if (unlikely(Rc(ctx->opcode) != 0))
1895
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1896
}
1897
/* sradi & sradi. */
1898
static always_inline void gen_sradi (DisasContext *ctx, int n)
1899
{
1900
    int sh = SH(ctx->opcode) + (n << 5);
1901
    if (sh != 0) {
1902
        int l1, l2;
1903
        TCGv t0;
1904
        l1 = gen_new_label();
1905
        l2 = gen_new_label();
1906
        t0 = tcg_temp_local_new();
1907
        tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
1908
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1909
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1910
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1911
        tcg_gen_br(l2);
1912
        gen_set_label(l1);
1913
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1914
        gen_set_label(l2);
1915
        tcg_temp_free(t0);
1916
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1917
    } else {
1918
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1919
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1920
    }
1921
    if (unlikely(Rc(ctx->opcode) != 0))
1922
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1923
}
1924

    
1925
static void gen_sradi0(DisasContext *ctx)
1926
{
1927
    gen_sradi(ctx, 0);
1928
}
1929

    
1930
static void gen_sradi1(DisasContext *ctx)
1931
{
1932
    gen_sradi(ctx, 1);
1933
}
1934

    
1935
/* srd & srd. */
1936
static void gen_srd(DisasContext *ctx)
1937
{
1938
    TCGv t0;
1939
    int l1, l2;
1940
    l1 = gen_new_label();
1941
    l2 = gen_new_label();
1942

    
1943
    t0 = tcg_temp_local_new();
1944
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
1945
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
1946
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1947
    tcg_gen_br(l2);
1948
    gen_set_label(l1);
1949
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
1950
    gen_set_label(l2);
1951
    tcg_temp_free(t0);
1952
    if (unlikely(Rc(ctx->opcode) != 0))
1953
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1954
}
1955
#endif
1956

    
1957
/***                       Floating-Point arithmetic                       ***/
1958
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
1959
static void gen_f##name(DisasContext *ctx)                                    \
1960
{                                                                             \
1961
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1962
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
1963
        return;                                                               \
1964
    }                                                                         \
1965
    /* NIP cannot be restored if the memory exception comes from an helper */ \
1966
    gen_update_nip(ctx, ctx->nip - 4);                                        \
1967
    gen_reset_fpstatus();                                                     \
1968
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
1969
                     cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
1970
    if (isfloat) {                                                            \
1971
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
1972
    }                                                                         \
1973
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf,                      \
1974
                     Rc(ctx->opcode) != 0);                                   \
1975
}
1976

    
1977
#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
1978
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
1979
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
1980

    
1981
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
1982
static void gen_f##name(DisasContext *ctx)                                    \
1983
{                                                                             \
1984
    if (unlikely(!ctx->fpu_enabled)) {                                        \
1985
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
1986
        return;                                                               \
1987
    }                                                                         \
1988
    /* NIP cannot be restored if the memory exception comes from an helper */ \
1989
    gen_update_nip(ctx, ctx->nip - 4);                                        \
1990
    gen_reset_fpstatus();                                                     \
1991
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
1992
                     cpu_fpr[rB(ctx->opcode)]);                               \
1993
    if (isfloat) {                                                            \
1994
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
1995
    }                                                                         \
1996
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
1997
                     set_fprf, Rc(ctx->opcode) != 0);                         \
1998
}
1999
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
2000
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2001
_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2002

    
2003
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2004
static void gen_f##name(DisasContext *ctx)                                    \
2005
{                                                                             \
2006
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2007
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2008
        return;                                                               \
2009
    }                                                                         \
2010
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2011
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2012
    gen_reset_fpstatus();                                                     \
2013
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
2014
                       cpu_fpr[rC(ctx->opcode)]);                             \
2015
    if (isfloat) {                                                            \
2016
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2017
    }                                                                         \
2018
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2019
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2020
}
2021
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
2022
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2023
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2024

    
2025
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2026
static void gen_f##name(DisasContext *ctx)                                    \
2027
{                                                                             \
2028
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2029
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2030
        return;                                                               \
2031
    }                                                                         \
2032
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2033
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2034
    gen_reset_fpstatus();                                                     \
2035
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2036
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2037
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2038
}
2039

    
2040
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2041
static void gen_f##name(DisasContext *ctx)                                    \
2042
{                                                                             \
2043
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2044
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2045
        return;                                                               \
2046
    }                                                                         \
2047
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2048
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2049
    gen_reset_fpstatus();                                                     \
2050
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2051
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2052
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2053
}
2054

    
2055
/* fadd - fadds */
2056
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2057
/* fdiv - fdivs */
2058
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2059
/* fmul - fmuls */
2060
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
2061

    
2062
/* fre */
2063
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2064

    
2065
/* fres */
2066
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
2067

    
2068
/* frsqrte */
2069
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2070

    
2071
/* frsqrtes */
2072
static void gen_frsqrtes(DisasContext *ctx)
2073
{
2074
    if (unlikely(!ctx->fpu_enabled)) {
2075
        gen_exception(ctx, POWERPC_EXCP_FPU);
2076
        return;
2077
    }
2078
    /* NIP cannot be restored if the memory exception comes from an helper */
2079
    gen_update_nip(ctx, ctx->nip - 4);
2080
    gen_reset_fpstatus();
2081
    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2082
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2083
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2084
}
2085

    
2086
/* fsel */
2087
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2088
/* fsub - fsubs */
2089
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
2090
/* Optional: */
2091

    
2092
/* fsqrt */
2093
static void gen_fsqrt(DisasContext *ctx)
2094
{
2095
    if (unlikely(!ctx->fpu_enabled)) {
2096
        gen_exception(ctx, POWERPC_EXCP_FPU);
2097
        return;
2098
    }
2099
    /* NIP cannot be restored if the memory exception comes from an helper */
2100
    gen_update_nip(ctx, ctx->nip - 4);
2101
    gen_reset_fpstatus();
2102
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2103
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2104
}
2105

    
2106
static void gen_fsqrts(DisasContext *ctx)
2107
{
2108
    if (unlikely(!ctx->fpu_enabled)) {
2109
        gen_exception(ctx, POWERPC_EXCP_FPU);
2110
        return;
2111
    }
2112
    /* NIP cannot be restored if the memory exception comes from an helper */
2113
    gen_update_nip(ctx, ctx->nip - 4);
2114
    gen_reset_fpstatus();
2115
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2116
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2117
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2118
}
2119

    
2120
/***                     Floating-Point multiply-and-add                   ***/
2121
/* fmadd - fmadds */
2122
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2123
/* fmsub - fmsubs */
2124
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2125
/* fnmadd - fnmadds */
2126
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2127
/* fnmsub - fnmsubs */
2128
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
2129

    
2130
/***                     Floating-Point round & convert                    ***/
2131
/* fctiw */
2132
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
2133
/* fctiwz */
2134
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
2135
/* frsp */
2136
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
2137
#if defined(TARGET_PPC64)
2138
/* fcfid */
2139
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
2140
/* fctid */
2141
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
2142
/* fctidz */
2143
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
2144
#endif
2145

    
2146
/* frin */
2147
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2148
/* friz */
2149
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2150
/* frip */
2151
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2152
/* frim */
2153
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2154

    
2155
/***                         Floating-Point compare                        ***/
2156

    
2157
/* fcmpo */
2158
static void gen_fcmpo(DisasContext *ctx)
2159
{
2160
    TCGv_i32 crf;
2161
    if (unlikely(!ctx->fpu_enabled)) {
2162
        gen_exception(ctx, POWERPC_EXCP_FPU);
2163
        return;
2164
    }
2165
    /* NIP cannot be restored if the memory exception comes from an helper */
2166
    gen_update_nip(ctx, ctx->nip - 4);
2167
    gen_reset_fpstatus();
2168
    crf = tcg_const_i32(crfD(ctx->opcode));
2169
    gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2170
    tcg_temp_free_i32(crf);
2171
    gen_helper_float_check_status();
2172
}
2173

    
2174
/* fcmpu */
2175
static void gen_fcmpu(DisasContext *ctx)
2176
{
2177
    TCGv_i32 crf;
2178
    if (unlikely(!ctx->fpu_enabled)) {
2179
        gen_exception(ctx, POWERPC_EXCP_FPU);
2180
        return;
2181
    }
2182
    /* NIP cannot be restored if the memory exception comes from an helper */
2183
    gen_update_nip(ctx, ctx->nip - 4);
2184
    gen_reset_fpstatus();
2185
    crf = tcg_const_i32(crfD(ctx->opcode));
2186
    gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2187
    tcg_temp_free_i32(crf);
2188
    gen_helper_float_check_status();
2189
}
2190

    
2191
/***                         Floating-point move                           ***/
2192
/* fabs */
2193
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2194
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2195

    
2196
/* fmr  - fmr. */
2197
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2198
static void gen_fmr(DisasContext *ctx)
2199
{
2200
    if (unlikely(!ctx->fpu_enabled)) {
2201
        gen_exception(ctx, POWERPC_EXCP_FPU);
2202
        return;
2203
    }
2204
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2205
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2206
}
2207

    
2208
/* fnabs */
2209
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2210
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2211
/* fneg */
2212
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2213
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2214

    
2215
/***                  Floating-Point status & ctrl register                ***/
2216

    
2217
/* mcrfs */
2218
static void gen_mcrfs(DisasContext *ctx)
2219
{
2220
    int bfa;
2221

    
2222
    if (unlikely(!ctx->fpu_enabled)) {
2223
        gen_exception(ctx, POWERPC_EXCP_FPU);
2224
        return;
2225
    }
2226
    bfa = 4 * (7 - crfS(ctx->opcode));
2227
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
2228
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2229
    tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
2230
}
2231

    
2232
/* mffs */
2233
static void gen_mffs(DisasContext *ctx)
2234
{
2235
    if (unlikely(!ctx->fpu_enabled)) {
2236
        gen_exception(ctx, POWERPC_EXCP_FPU);
2237
        return;
2238
    }
2239
    gen_reset_fpstatus();
2240
    tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2241
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2242
}
2243

    
2244
/* mtfsb0 */
2245
static void gen_mtfsb0(DisasContext *ctx)
2246
{
2247
    uint8_t crb;
2248

    
2249
    if (unlikely(!ctx->fpu_enabled)) {
2250
        gen_exception(ctx, POWERPC_EXCP_FPU);
2251
        return;
2252
    }
2253
    crb = 31 - crbD(ctx->opcode);
2254
    gen_reset_fpstatus();
2255
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2256
        TCGv_i32 t0;
2257
        /* NIP cannot be restored if the memory exception comes from an helper */
2258
        gen_update_nip(ctx, ctx->nip - 4);
2259
        t0 = tcg_const_i32(crb);
2260
        gen_helper_fpscr_clrbit(t0);
2261
        tcg_temp_free_i32(t0);
2262
    }
2263
    if (unlikely(Rc(ctx->opcode) != 0)) {
2264
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2265
    }
2266
}
2267

    
2268
/* mtfsb1 */
2269
static void gen_mtfsb1(DisasContext *ctx)
2270
{
2271
    uint8_t crb;
2272

    
2273
    if (unlikely(!ctx->fpu_enabled)) {
2274
        gen_exception(ctx, POWERPC_EXCP_FPU);
2275
        return;
2276
    }
2277
    crb = 31 - crbD(ctx->opcode);
2278
    gen_reset_fpstatus();
2279
    /* XXX: we pretend we can only do IEEE floating-point computations */
2280
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2281
        TCGv_i32 t0;
2282
        /* NIP cannot be restored if the memory exception comes from an helper */
2283
        gen_update_nip(ctx, ctx->nip - 4);
2284
        t0 = tcg_const_i32(crb);
2285
        gen_helper_fpscr_setbit(t0);
2286
        tcg_temp_free_i32(t0);
2287
    }
2288
    if (unlikely(Rc(ctx->opcode) != 0)) {
2289
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2290
    }
2291
    /* We can raise a differed exception */
2292
    gen_helper_float_check_status();
2293
}
2294

    
2295
/* mtfsf */
2296
static void gen_mtfsf(DisasContext *ctx)
2297
{
2298
    TCGv_i32 t0;
2299
    int L = ctx->opcode & 0x02000000;
2300

    
2301
    if (unlikely(!ctx->fpu_enabled)) {
2302
        gen_exception(ctx, POWERPC_EXCP_FPU);
2303
        return;
2304
    }
2305
    /* NIP cannot be restored if the memory exception comes from an helper */
2306
    gen_update_nip(ctx, ctx->nip - 4);
2307
    gen_reset_fpstatus();
2308
    if (L)
2309
        t0 = tcg_const_i32(0xff);
2310
    else
2311
        t0 = tcg_const_i32(FM(ctx->opcode));
2312
    gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
2313
    tcg_temp_free_i32(t0);
2314
    if (unlikely(Rc(ctx->opcode) != 0)) {
2315
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2316
    }
2317
    /* We can raise a differed exception */
2318
    gen_helper_float_check_status();
2319
}
2320

    
2321
/* mtfsfi */
2322
static void gen_mtfsfi(DisasContext *ctx)
2323
{
2324
    int bf, sh;
2325
    TCGv_i64 t0;
2326
    TCGv_i32 t1;
2327

    
2328
    if (unlikely(!ctx->fpu_enabled)) {
2329
        gen_exception(ctx, POWERPC_EXCP_FPU);
2330
        return;
2331
    }
2332
    bf = crbD(ctx->opcode) >> 2;
2333
    sh = 7 - bf;
2334
    /* NIP cannot be restored if the memory exception comes from an helper */
2335
    gen_update_nip(ctx, ctx->nip - 4);
2336
    gen_reset_fpstatus();
2337
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
2338
    t1 = tcg_const_i32(1 << sh);
2339
    gen_helper_store_fpscr(t0, t1);
2340
    tcg_temp_free_i64(t0);
2341
    tcg_temp_free_i32(t1);
2342
    if (unlikely(Rc(ctx->opcode) != 0)) {
2343
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2344
    }
2345
    /* We can raise a differed exception */
2346
    gen_helper_float_check_status();
2347
}
2348

    
2349
/***                           Addressing modes                            ***/
2350
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2351
static always_inline void gen_addr_imm_index (DisasContext *ctx, TCGv EA, target_long maskl)
2352
{
2353
    target_long simm = SIMM(ctx->opcode);
2354

    
2355
    simm &= ~maskl;
2356
    if (rA(ctx->opcode) == 0) {
2357
#if defined(TARGET_PPC64)
2358
        if (!ctx->sf_mode) {
2359
            tcg_gen_movi_tl(EA, (uint32_t)simm);
2360
        } else
2361
#endif
2362
        tcg_gen_movi_tl(EA, simm);
2363
    } else if (likely(simm != 0)) {
2364
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2365
#if defined(TARGET_PPC64)
2366
        if (!ctx->sf_mode) {
2367
            tcg_gen_ext32u_tl(EA, EA);
2368
        }
2369
#endif
2370
    } else {
2371
#if defined(TARGET_PPC64)
2372
        if (!ctx->sf_mode) {
2373
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2374
        } else
2375
#endif
2376
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2377
    }
2378
}
2379

    
2380
static always_inline void gen_addr_reg_index (DisasContext *ctx, TCGv EA)
2381
{
2382
    if (rA(ctx->opcode) == 0) {
2383
#if defined(TARGET_PPC64)
2384
        if (!ctx->sf_mode) {
2385
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2386
        } else
2387
#endif
2388
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2389
    } else {
2390
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2391
#if defined(TARGET_PPC64)
2392
        if (!ctx->sf_mode) {
2393
            tcg_gen_ext32u_tl(EA, EA);
2394
        }
2395
#endif
2396
    }
2397
}
2398

    
2399
static always_inline void gen_addr_register (DisasContext *ctx, TCGv EA)
2400
{
2401
    if (rA(ctx->opcode) == 0) {
2402
        tcg_gen_movi_tl(EA, 0);
2403
    } else {
2404
#if defined(TARGET_PPC64)
2405
        if (!ctx->sf_mode) {
2406
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2407
        } else
2408
#endif
2409
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2410
    }
2411
}
2412

    
2413
static always_inline void gen_addr_add (DisasContext *ctx, TCGv ret, TCGv arg1, target_long val)
2414
{
2415
    tcg_gen_addi_tl(ret, arg1, val);
2416
#if defined(TARGET_PPC64)
2417
    if (!ctx->sf_mode) {
2418
        tcg_gen_ext32u_tl(ret, ret);
2419
    }
2420
#endif
2421
}
2422

    
2423
static always_inline void gen_check_align (DisasContext *ctx, TCGv EA, int mask)
2424
{
2425
    int l1 = gen_new_label();
2426
    TCGv t0 = tcg_temp_new();
2427
    TCGv_i32 t1, t2;
2428
    /* NIP cannot be restored if the memory exception comes from an helper */
2429
    gen_update_nip(ctx, ctx->nip - 4);
2430
    tcg_gen_andi_tl(t0, EA, mask);
2431
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2432
    t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2433
    t2 = tcg_const_i32(0);
2434
    gen_helper_raise_exception_err(t1, t2);
2435
    tcg_temp_free_i32(t1);
2436
    tcg_temp_free_i32(t2);
2437
    gen_set_label(l1);
2438
    tcg_temp_free(t0);
2439
}
2440

    
2441
/***                             Integer load                              ***/
2442
static always_inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2443
{
2444
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2445
}
2446

    
2447
static always_inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2448
{
2449
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
2450
}
2451

    
2452
static always_inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2453
{
2454
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2455
    if (unlikely(ctx->le_mode)) {
2456
        tcg_gen_bswap16_tl(arg1, arg1);
2457
    }
2458
}
2459

    
2460
static always_inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2461
{
2462
    if (unlikely(ctx->le_mode)) {
2463
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2464
        tcg_gen_bswap16_tl(arg1, arg1);
2465
        tcg_gen_ext16s_tl(arg1, arg1);
2466
    } else {
2467
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
2468
    }
2469
}
2470

    
2471
static always_inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2472
{
2473
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2474
    if (unlikely(ctx->le_mode)) {
2475
        tcg_gen_bswap32_tl(arg1, arg1);
2476
    }
2477
}
2478

    
2479
#if defined(TARGET_PPC64)
2480
static always_inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2481
{
2482
    if (unlikely(ctx->le_mode)) {
2483
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2484
        tcg_gen_bswap32_tl(arg1, arg1);
2485
        tcg_gen_ext32s_tl(arg1, arg1);
2486
    } else
2487
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
2488
}
2489
#endif
2490

    
2491
static always_inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2492
{
2493
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
2494
    if (unlikely(ctx->le_mode)) {
2495
        tcg_gen_bswap64_i64(arg1, arg1);
2496
    }
2497
}
2498

    
2499
static always_inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
2500
{
2501
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
2502
}
2503

    
2504
static always_inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
2505
{
2506
    if (unlikely(ctx->le_mode)) {
2507
        TCGv t0 = tcg_temp_new();
2508
        tcg_gen_ext16u_tl(t0, arg1);
2509
        tcg_gen_bswap16_tl(t0, t0);
2510
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2511
        tcg_temp_free(t0);
2512
    } else {
2513
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2514
    }
2515
}
2516

    
2517
static always_inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
2518
{
2519
    if (unlikely(ctx->le_mode)) {
2520
        TCGv t0 = tcg_temp_new();
2521
        tcg_gen_ext32u_tl(t0, arg1);
2522
        tcg_gen_bswap32_tl(t0, t0);
2523
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2524
        tcg_temp_free(t0);
2525
    } else {
2526
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2527
    }
2528
}
2529

    
2530
static always_inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2531
{
2532
    if (unlikely(ctx->le_mode)) {
2533
        TCGv_i64 t0 = tcg_temp_new_i64();
2534
        tcg_gen_bswap64_i64(t0, arg1);
2535
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
2536
        tcg_temp_free_i64(t0);
2537
    } else
2538
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
2539
}
2540

    
2541
#define GEN_LD(name, ldop, opc, type)                                         \
2542
static void glue(gen_, name)(DisasContext *ctx)                                       \
2543
{                                                                             \
2544
    TCGv EA;                                                                  \
2545
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2546
    EA = tcg_temp_new();                                                      \
2547
    gen_addr_imm_index(ctx, EA, 0);                                           \
2548
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2549
    tcg_temp_free(EA);                                                        \
2550
}
2551

    
2552
#define GEN_LDU(name, ldop, opc, type)                                        \
2553
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
2554
{                                                                             \
2555
    TCGv EA;                                                                  \
2556
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2557
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2558
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2559
        return;                                                               \
2560
    }                                                                         \
2561
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2562
    EA = tcg_temp_new();                                                      \
2563
    if (type == PPC_64B)                                                      \
2564
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2565
    else                                                                      \
2566
        gen_addr_imm_index(ctx, EA, 0);                                       \
2567
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2568
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2569
    tcg_temp_free(EA);                                                        \
2570
}
2571

    
2572
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
2573
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
2574
{                                                                             \
2575
    TCGv EA;                                                                  \
2576
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2577
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2578
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2579
        return;                                                               \
2580
    }                                                                         \
2581
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2582
    EA = tcg_temp_new();                                                      \
2583
    gen_addr_reg_index(ctx, EA);                                              \
2584
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2585
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2586
    tcg_temp_free(EA);                                                        \
2587
}
2588

    
2589
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
2590
static void glue(gen_, name##x)(DisasContext *ctx)                            \
2591
{                                                                             \
2592
    TCGv EA;                                                                  \
2593
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2594
    EA = tcg_temp_new();                                                      \
2595
    gen_addr_reg_index(ctx, EA);                                              \
2596
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2597
    tcg_temp_free(EA);                                                        \
2598
}
2599

    
2600
#define GEN_LDS(name, ldop, op, type)                                         \
2601
GEN_LD(name, ldop, op | 0x20, type);                                          \
2602
GEN_LDU(name, ldop, op | 0x21, type);                                         \
2603
GEN_LDUX(name, ldop, 0x17, op | 0x01, type);                                  \
2604
GEN_LDX(name, ldop, 0x17, op | 0x00, type)
2605

    
2606
/* lbz lbzu lbzux lbzx */
2607
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
2608
/* lha lhau lhaux lhax */
2609
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
2610
/* lhz lhzu lhzux lhzx */
2611
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
2612
/* lwz lwzu lwzux lwzx */
2613
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2614
#if defined(TARGET_PPC64)
2615
/* lwaux */
2616
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2617
/* lwax */
2618
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2619
/* ldux */
2620
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2621
/* ldx */
2622
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
2623

    
2624
static void gen_ld(DisasContext *ctx)
2625
{
2626
    TCGv EA;
2627
    if (Rc(ctx->opcode)) {
2628
        if (unlikely(rA(ctx->opcode) == 0 ||
2629
                     rA(ctx->opcode) == rD(ctx->opcode))) {
2630
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2631
            return;
2632
        }
2633
    }
2634
    gen_set_access_type(ctx, ACCESS_INT);
2635
    EA = tcg_temp_new();
2636
    gen_addr_imm_index(ctx, EA, 0x03);
2637
    if (ctx->opcode & 0x02) {
2638
        /* lwa (lwau is undefined) */
2639
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2640
    } else {
2641
        /* ld - ldu */
2642
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2643
    }
2644
    if (Rc(ctx->opcode))
2645
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2646
    tcg_temp_free(EA);
2647
}
2648

    
2649
/* lq */
2650
static void gen_lq(DisasContext *ctx)
2651
{
2652
#if defined(CONFIG_USER_ONLY)
2653
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2654
#else
2655
    int ra, rd;
2656
    TCGv EA;
2657

    
2658
    /* Restore CPU state */
2659
    if (unlikely(ctx->mem_idx == 0)) {
2660
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2661
        return;
2662
    }
2663
    ra = rA(ctx->opcode);
2664
    rd = rD(ctx->opcode);
2665
    if (unlikely((rd & 1) || rd == ra)) {
2666
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2667
        return;
2668
    }
2669
    if (unlikely(ctx->le_mode)) {
2670
        /* Little-endian mode is not handled */
2671
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2672
        return;
2673
    }
2674
    gen_set_access_type(ctx, ACCESS_INT);
2675
    EA = tcg_temp_new();
2676
    gen_addr_imm_index(ctx, EA, 0x0F);
2677
    gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2678
    gen_addr_add(ctx, EA, EA, 8);
2679
    gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
2680
    tcg_temp_free(EA);
2681
#endif
2682
}
2683
#endif
2684

    
2685
/***                              Integer store                            ***/
2686
#define GEN_ST(name, stop, opc, type)                                         \
2687
static void glue(gen_, name)(DisasContext *ctx)                                       \
2688
{                                                                             \
2689
    TCGv EA;                                                                  \
2690
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2691
    EA = tcg_temp_new();                                                      \
2692
    gen_addr_imm_index(ctx, EA, 0);                                           \
2693
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2694
    tcg_temp_free(EA);                                                        \
2695
}
2696

    
2697
#define GEN_STU(name, stop, opc, type)                                        \
2698
static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
2699
{                                                                             \
2700
    TCGv EA;                                                                  \
2701
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2702
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2703
        return;                                                               \
2704
    }                                                                         \
2705
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2706
    EA = tcg_temp_new();                                                      \
2707
    if (type == PPC_64B)                                                      \
2708
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2709
    else                                                                      \
2710
        gen_addr_imm_index(ctx, EA, 0);                                       \
2711
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2712
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2713
    tcg_temp_free(EA);                                                        \
2714
}
2715

    
2716
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
2717
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
2718
{                                                                             \
2719
    TCGv EA;                                                                  \
2720
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2721
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2722
        return;                                                               \
2723
    }                                                                         \
2724
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2725
    EA = tcg_temp_new();                                                      \
2726
    gen_addr_reg_index(ctx, EA);                                              \
2727
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2728
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2729
    tcg_temp_free(EA);                                                        \
2730
}
2731

    
2732
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
2733
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
2734
{                                                                             \
2735
    TCGv EA;                                                                  \
2736
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2737
    EA = tcg_temp_new();                                                      \
2738
    gen_addr_reg_index(ctx, EA);                                              \
2739
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2740
    tcg_temp_free(EA);                                                        \
2741
}
2742

    
2743
#define GEN_STS(name, stop, op, type)                                         \
2744
GEN_ST(name, stop, op | 0x20, type);                                          \
2745
GEN_STU(name, stop, op | 0x21, type);                                         \
2746
GEN_STUX(name, stop, 0x17, op | 0x01, type);                                  \
2747
GEN_STX(name, stop, 0x17, op | 0x00, type)
2748

    
2749
/* stb stbu stbux stbx */
2750
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
2751
/* sth sthu sthux sthx */
2752
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
2753
/* stw stwu stwux stwx */
2754
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2755
#if defined(TARGET_PPC64)
2756
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
2757
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
2758

    
2759
static void gen_std(DisasContext *ctx)
2760
{
2761
    int rs;
2762
    TCGv EA;
2763

    
2764
    rs = rS(ctx->opcode);
2765
    if ((ctx->opcode & 0x3) == 0x2) {
2766
#if defined(CONFIG_USER_ONLY)
2767
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2768
#else
2769
        /* stq */
2770
        if (unlikely(ctx->mem_idx == 0)) {
2771
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2772
            return;
2773
        }
2774
        if (unlikely(rs & 1)) {
2775
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2776
            return;
2777
        }
2778
        if (unlikely(ctx->le_mode)) {
2779
            /* Little-endian mode is not handled */
2780
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2781
            return;
2782
        }
2783
        gen_set_access_type(ctx, ACCESS_INT);
2784
        EA = tcg_temp_new();
2785
        gen_addr_imm_index(ctx, EA, 0x03);
2786
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2787
        gen_addr_add(ctx, EA, EA, 8);
2788
        gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
2789
        tcg_temp_free(EA);
2790
#endif
2791
    } else {
2792
        /* std / stdu */
2793
        if (Rc(ctx->opcode)) {
2794
            if (unlikely(rA(ctx->opcode) == 0)) {
2795
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2796
                return;
2797
            }
2798
        }
2799
        gen_set_access_type(ctx, ACCESS_INT);
2800
        EA = tcg_temp_new();
2801
        gen_addr_imm_index(ctx, EA, 0x03);
2802
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2803
        if (Rc(ctx->opcode))
2804
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2805
        tcg_temp_free(EA);
2806
    }
2807
}
2808
#endif
2809
/***                Integer load and store with byte reverse               ***/
2810
/* lhbrx */
2811
static void always_inline gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
2812
{
2813
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2814
    if (likely(!ctx->le_mode)) {
2815
        tcg_gen_bswap16_tl(arg1, arg1);
2816
    }
2817
}
2818
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
2819

    
2820
/* lwbrx */
2821
static void always_inline gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
2822
{
2823
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2824
    if (likely(!ctx->le_mode)) {
2825
        tcg_gen_bswap32_tl(arg1, arg1);
2826
    }
2827
}
2828
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
2829

    
2830
/* sthbrx */
2831
static void always_inline gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
2832
{
2833
    if (likely(!ctx->le_mode)) {
2834
        TCGv t0 = tcg_temp_new();
2835
        tcg_gen_ext16u_tl(t0, arg1);
2836
        tcg_gen_bswap16_tl(t0, t0);
2837
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2838
        tcg_temp_free(t0);
2839
    } else {
2840
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2841
    }
2842
}
2843
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
2844

    
2845
/* stwbrx */
2846
static void always_inline gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
2847
{
2848
    if (likely(!ctx->le_mode)) {
2849
        TCGv t0 = tcg_temp_new();
2850
        tcg_gen_ext32u_tl(t0, arg1);
2851
        tcg_gen_bswap32_tl(t0, t0);
2852
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2853
        tcg_temp_free(t0);
2854
    } else {
2855
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2856
    }
2857
}
2858
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
2859

    
2860
/***                    Integer load and store multiple                    ***/
2861

    
2862
/* lmw */
2863
static void gen_lmw(DisasContext *ctx)
2864
{
2865
    TCGv t0;
2866
    TCGv_i32 t1;
2867
    gen_set_access_type(ctx, ACCESS_INT);
2868
    /* NIP cannot be restored if the memory exception comes from an helper */
2869
    gen_update_nip(ctx, ctx->nip - 4);
2870
    t0 = tcg_temp_new();
2871
    t1 = tcg_const_i32(rD(ctx->opcode));
2872
    gen_addr_imm_index(ctx, t0, 0);
2873
    gen_helper_lmw(t0, t1);
2874
    tcg_temp_free(t0);
2875
    tcg_temp_free_i32(t1);
2876
}
2877

    
2878
/* stmw */
2879
static void gen_stmw(DisasContext *ctx)
2880
{
2881
    TCGv t0;
2882
    TCGv_i32 t1;
2883
    gen_set_access_type(ctx, ACCESS_INT);
2884
    /* NIP cannot be restored if the memory exception comes from an helper */
2885
    gen_update_nip(ctx, ctx->nip - 4);
2886
    t0 = tcg_temp_new();
2887
    t1 = tcg_const_i32(rS(ctx->opcode));
2888
    gen_addr_imm_index(ctx, t0, 0);
2889
    gen_helper_stmw(t0, t1);
2890
    tcg_temp_free(t0);
2891
    tcg_temp_free_i32(t1);
2892
}
2893

    
2894
/***                    Integer load and store strings                     ***/
2895

    
2896
/* lswi */
2897
/* PowerPC32 specification says we must generate an exception if
2898
 * rA is in the range of registers to be loaded.
2899
 * In an other hand, IBM says this is valid, but rA won't be loaded.
2900
 * For now, I'll follow the spec...
2901
 */
2902
static void gen_lswi(DisasContext *ctx)
2903
{
2904
    TCGv t0;
2905
    TCGv_i32 t1, t2;
2906
    int nb = NB(ctx->opcode);
2907
    int start = rD(ctx->opcode);
2908
    int ra = rA(ctx->opcode);
2909
    int nr;
2910

    
2911
    if (nb == 0)
2912
        nb = 32;
2913
    nr = nb / 4;
2914
    if (unlikely(((start + nr) > 32  &&
2915
                  start <= ra && (start + nr - 32) > ra) ||
2916
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
2917
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
2918
        return;
2919
    }
2920
    gen_set_access_type(ctx, ACCESS_INT);
2921
    /* NIP cannot be restored if the memory exception comes from an helper */
2922
    gen_update_nip(ctx, ctx->nip - 4);
2923
    t0 = tcg_temp_new();
2924
    gen_addr_register(ctx, t0);
2925
    t1 = tcg_const_i32(nb);
2926
    t2 = tcg_const_i32(start);
2927
    gen_helper_lsw(t0, t1, t2);
2928
    tcg_temp_free(t0);
2929
    tcg_temp_free_i32(t1);
2930
    tcg_temp_free_i32(t2);
2931
}
2932

    
2933
/* lswx */
2934
static void gen_lswx(DisasContext *ctx)
2935
{
2936
    TCGv t0;
2937
    TCGv_i32 t1, t2, t3;
2938
    gen_set_access_type(ctx, ACCESS_INT);
2939
    /* NIP cannot be restored if the memory exception comes from an helper */
2940
    gen_update_nip(ctx, ctx->nip - 4);
2941
    t0 = tcg_temp_new();
2942
    gen_addr_reg_index(ctx, t0);
2943
    t1 = tcg_const_i32(rD(ctx->opcode));
2944
    t2 = tcg_const_i32(rA(ctx->opcode));
2945
    t3 = tcg_const_i32(rB(ctx->opcode));
2946
    gen_helper_lswx(t0, t1, t2, t3);
2947
    tcg_temp_free(t0);
2948
    tcg_temp_free_i32(t1);
2949
    tcg_temp_free_i32(t2);
2950
    tcg_temp_free_i32(t3);
2951
}
2952

    
2953
/* stswi */
2954
static void gen_stswi(DisasContext *ctx)
2955
{
2956
    TCGv t0;
2957
    TCGv_i32 t1, t2;
2958
    int nb = NB(ctx->opcode);
2959
    gen_set_access_type(ctx, ACCESS_INT);
2960
    /* NIP cannot be restored if the memory exception comes from an helper */
2961
    gen_update_nip(ctx, ctx->nip - 4);
2962
    t0 = tcg_temp_new();
2963
    gen_addr_register(ctx, t0);
2964
    if (nb == 0)
2965
        nb = 32;
2966
    t1 = tcg_const_i32(nb);
2967
    t2 = tcg_const_i32(rS(ctx->opcode));
2968
    gen_helper_stsw(t0, t1, t2);
2969
    tcg_temp_free(t0);
2970
    tcg_temp_free_i32(t1);
2971
    tcg_temp_free_i32(t2);
2972
}
2973

    
2974
/* stswx */
2975
static void gen_stswx(DisasContext *ctx)
2976
{
2977
    TCGv t0;
2978
    TCGv_i32 t1, t2;
2979
    gen_set_access_type(ctx, ACCESS_INT);
2980
    /* NIP cannot be restored if the memory exception comes from an helper */
2981
    gen_update_nip(ctx, ctx->nip - 4);
2982
    t0 = tcg_temp_new();
2983
    gen_addr_reg_index(ctx, t0);
2984
    t1 = tcg_temp_new_i32();
2985
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
2986
    tcg_gen_andi_i32(t1, t1, 0x7F);
2987
    t2 = tcg_const_i32(rS(ctx->opcode));
2988
    gen_helper_stsw(t0, t1, t2);
2989
    tcg_temp_free(t0);
2990
    tcg_temp_free_i32(t1);
2991
    tcg_temp_free_i32(t2);
2992
}
2993

    
2994
/***                        Memory synchronisation                         ***/
2995
/* eieio */
2996
static void gen_eieio(DisasContext *ctx)
2997
{
2998
}
2999

    
3000
/* isync */
3001
static void gen_isync(DisasContext *ctx)
3002
{
3003
    gen_stop_exception(ctx);
3004
}
3005

    
3006
/* lwarx */
3007
static void gen_lwarx(DisasContext *ctx)
3008
{
3009
    TCGv t0;
3010
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
3011
    gen_set_access_type(ctx, ACCESS_RES);
3012
    t0 = tcg_temp_local_new();
3013
    gen_addr_reg_index(ctx, t0);
3014
    gen_check_align(ctx, t0, 0x03);
3015
    gen_qemu_ld32u(ctx, gpr, t0);
3016
    tcg_gen_mov_tl(cpu_reserve, t0);
3017
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
3018
    tcg_temp_free(t0);
3019
}
3020

    
3021
/* stwcx. */
3022
static void gen_stwcx_(DisasContext *ctx)
3023
{
3024
    int l1;
3025
    TCGv t0;
3026
    gen_set_access_type(ctx, ACCESS_RES);
3027
    t0 = tcg_temp_local_new();
3028
    gen_addr_reg_index(ctx, t0);
3029
    gen_check_align(ctx, t0, 0x03);
3030
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3031
    tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3032
    tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3033
    l1 = gen_new_label();
3034
    tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3035
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3036
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3037
    gen_set_label(l1);
3038
    tcg_gen_movi_tl(cpu_reserve, -1);
3039
    tcg_temp_free(t0);
3040
}
3041

    
3042
#if defined(TARGET_PPC64)
3043
/* ldarx */
3044
static void gen_ldarx(DisasContext *ctx)
3045
{
3046
    TCGv t0;
3047
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
3048
    gen_set_access_type(ctx, ACCESS_RES);
3049
    t0 = tcg_temp_local_new();
3050
    gen_addr_reg_index(ctx, t0);
3051
    gen_check_align(ctx, t0, 0x07);
3052
    gen_qemu_ld64(ctx, gpr, t0);
3053
    tcg_gen_mov_tl(cpu_reserve, t0);
3054
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
3055
    tcg_temp_free(t0);
3056
}
3057

    
3058
/* stdcx. */
3059
static void gen_stdcx_(DisasContext *ctx)
3060
{
3061
    int l1;
3062
    TCGv t0;
3063
    gen_set_access_type(ctx, ACCESS_RES);
3064
    t0 = tcg_temp_local_new();
3065
    gen_addr_reg_index(ctx, t0);
3066
    gen_check_align(ctx, t0, 0x07);
3067
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3068
    tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3069
    tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3070
    l1 = gen_new_label();
3071
    tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3072
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3073
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3074
    gen_set_label(l1);
3075
    tcg_gen_movi_tl(cpu_reserve, -1);
3076
    tcg_temp_free(t0);
3077
}
3078
#endif /* defined(TARGET_PPC64) */
3079

    
3080
/* sync */
3081
static void gen_sync(DisasContext *ctx)
3082
{
3083
}
3084

    
3085
/* wait */
3086
static void gen_wait(DisasContext *ctx)
3087
{
3088
    TCGv_i32 t0 = tcg_temp_new_i32();
3089
    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
3090
    tcg_temp_free_i32(t0);
3091
    /* Stop translation, as the CPU is supposed to sleep from now */
3092
    gen_exception_err(ctx, EXCP_HLT, 1);
3093
}
3094

    
3095
/***                         Floating-point load                           ***/
3096
#define GEN_LDF(name, ldop, opc, type)                                        \
3097
static void glue(gen_, name)(DisasContext *ctx)                                       \
3098
{                                                                             \
3099
    TCGv EA;                                                                  \
3100
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3101
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3102
        return;                                                               \
3103
    }                                                                         \
3104
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3105
    EA = tcg_temp_new();                                                      \
3106
    gen_addr_imm_index(ctx, EA, 0);                                           \
3107
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3108
    tcg_temp_free(EA);                                                        \
3109
}
3110

    
3111
#define GEN_LDUF(name, ldop, opc, type)                                       \
3112
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
3113
{                                                                             \
3114
    TCGv EA;                                                                  \
3115
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3116
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3117
        return;                                                               \
3118
    }                                                                         \
3119
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3120
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3121
        return;                                                               \
3122
    }                                                                         \
3123
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3124
    EA = tcg_temp_new();                                                      \
3125
    gen_addr_imm_index(ctx, EA, 0);                                           \
3126
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3127
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3128
    tcg_temp_free(EA);                                                        \
3129
}
3130

    
3131
#define GEN_LDUXF(name, ldop, opc, type)                                      \
3132
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3133
{                                                                             \
3134
    TCGv EA;                                                                  \
3135
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3136
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3137
        return;                                                               \
3138
    }                                                                         \
3139
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3140
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3141
        return;                                                               \
3142
    }                                                                         \
3143
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3144
    EA = tcg_temp_new();                                                      \
3145
    gen_addr_reg_index(ctx, EA);                                              \
3146
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3147
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3148
    tcg_temp_free(EA);                                                        \
3149
}
3150

    
3151
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
3152
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
3153
{                                                                             \
3154
    TCGv EA;                                                                  \
3155
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3156
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3157
        return;                                                               \
3158
    }                                                                         \
3159
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3160
    EA = tcg_temp_new();                                                      \
3161
    gen_addr_reg_index(ctx, EA);                                              \
3162
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3163
    tcg_temp_free(EA);                                                        \
3164
}
3165

    
3166
#define GEN_LDFS(name, ldop, op, type)                                        \
3167
GEN_LDF(name, ldop, op | 0x20, type);                                         \
3168
GEN_LDUF(name, ldop, op | 0x21, type);                                        \
3169
GEN_LDUXF(name, ldop, op | 0x01, type);                                       \
3170
GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3171

    
3172
static always_inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3173
{
3174
    TCGv t0 = tcg_temp_new();
3175
    TCGv_i32 t1 = tcg_temp_new_i32();
3176
    gen_qemu_ld32u(ctx, t0, arg2);
3177
    tcg_gen_trunc_tl_i32(t1, t0);
3178
    tcg_temp_free(t0);
3179
    gen_helper_float32_to_float64(arg1, t1);
3180
    tcg_temp_free_i32(t1);
3181
}
3182

    
3183
 /* lfd lfdu lfdux lfdx */
3184
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3185
 /* lfs lfsu lfsux lfsx */
3186
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
3187

    
3188
/***                         Floating-point store                          ***/
3189
#define GEN_STF(name, stop, opc, type)                                        \
3190
static void glue(gen_, name)(DisasContext *ctx)                                       \
3191
{                                                                             \
3192
    TCGv EA;                                                                  \
3193
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3194
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3195
        return;                                                               \
3196
    }                                                                         \
3197
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3198
    EA = tcg_temp_new();                                                      \
3199
    gen_addr_imm_index(ctx, EA, 0);                                           \
3200
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3201
    tcg_temp_free(EA);                                                        \
3202
}
3203

    
3204
#define GEN_STUF(name, stop, opc, type)                                       \
3205
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
3206
{                                                                             \
3207
    TCGv EA;                                                                  \
3208
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3209
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3210
        return;                                                               \
3211
    }                                                                         \
3212
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3213
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3214
        return;                                                               \
3215
    }                                                                         \
3216
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3217
    EA = tcg_temp_new();                                                      \
3218
    gen_addr_imm_index(ctx, EA, 0);                                           \
3219
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3220
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3221
    tcg_temp_free(EA);                                                        \
3222
}
3223

    
3224
#define GEN_STUXF(name, stop, opc, type)                                      \
3225
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3226
{                                                                             \
3227
    TCGv EA;                                                                  \
3228
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3229
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3230
        return;                                                               \
3231
    }                                                                         \
3232
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3233
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3234
        return;                                                               \
3235
    }                                                                         \
3236
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3237
    EA = tcg_temp_new();                                                      \
3238
    gen_addr_reg_index(ctx, EA);                                              \
3239
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3240
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3241
    tcg_temp_free(EA);                                                        \
3242
}
3243

    
3244
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
3245
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
3246
{                                                                             \
3247
    TCGv EA;                                                                  \
3248
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3249
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3250
        return;                                                               \
3251
    }                                                                         \
3252
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3253
    EA = tcg_temp_new();                                                      \
3254
    gen_addr_reg_index(ctx, EA);                                              \
3255
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3256
    tcg_temp_free(EA);                                                        \
3257
}
3258

    
3259
#define GEN_STFS(name, stop, op, type)                                        \
3260
GEN_STF(name, stop, op | 0x20, type);                                         \
3261
GEN_STUF(name, stop, op | 0x21, type);                                        \
3262
GEN_STUXF(name, stop, op | 0x01, type);                                       \
3263
GEN_STXF(name, stop, 0x17, op | 0x00, type)
3264

    
3265
static always_inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3266
{
3267
    TCGv_i32 t0 = tcg_temp_new_i32();
3268
    TCGv t1 = tcg_temp_new();
3269
    gen_helper_float64_to_float32(t0, arg1);
3270
    tcg_gen_extu_i32_tl(t1, t0);
3271
    tcg_temp_free_i32(t0);
3272
    gen_qemu_st32(ctx, t1, arg2);
3273
    tcg_temp_free(t1);
3274
}
3275

    
3276
/* stfd stfdu stfdux stfdx */
3277
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
3278
/* stfs stfsu stfsux stfsx */
3279
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
3280

    
3281
/* Optional: */
3282
static always_inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3283
{
3284
    TCGv t0 = tcg_temp_new();
3285
    tcg_gen_trunc_i64_tl(t0, arg1),
3286
    gen_qemu_st32(ctx, t0, arg2);
3287
    tcg_temp_free(t0);
3288
}
3289
/* stfiwx */
3290
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
3291

    
3292
/***                                Branch                                 ***/
3293
static always_inline void gen_goto_tb (DisasContext *ctx, int n,
3294
                                       target_ulong dest)
3295
{
3296
    TranslationBlock *tb;
3297
    tb = ctx->tb;
3298
#if defined(TARGET_PPC64)
3299
    if (!ctx->sf_mode)
3300
        dest = (uint32_t) dest;
3301
#endif
3302
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3303
        likely(!ctx->singlestep_enabled)) {
3304
        tcg_gen_goto_tb(n);
3305
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3306
        tcg_gen_exit_tb((long)tb + n);
3307
    } else {
3308
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3309
        if (unlikely(ctx->singlestep_enabled)) {
3310
            if ((ctx->singlestep_enabled &
3311
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3312
                ctx->exception == POWERPC_EXCP_BRANCH) {
3313
                target_ulong tmp = ctx->nip;
3314
                ctx->nip = dest;
3315
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3316
                ctx->nip = tmp;
3317
            }
3318
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3319
                gen_debug_exception(ctx);
3320
            }
3321
        }
3322
        tcg_gen_exit_tb(0);
3323
    }
3324
}
3325

    
3326
static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
3327
{
3328
#if defined(TARGET_PPC64)
3329
    if (ctx->sf_mode == 0)
3330
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3331
    else
3332
#endif
3333
        tcg_gen_movi_tl(cpu_lr, nip);
3334
}
3335

    
3336
/* b ba bl bla */
3337
static void gen_b(DisasContext *ctx)
3338
{
3339
    target_ulong li, target;
3340

    
3341
    ctx->exception = POWERPC_EXCP_BRANCH;
3342
    /* sign extend LI */
3343
#if defined(TARGET_PPC64)
3344
    if (ctx->sf_mode)
3345
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3346
    else
3347
#endif
3348
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3349
    if (likely(AA(ctx->opcode) == 0))
3350
        target = ctx->nip + li - 4;
3351
    else
3352
        target = li;
3353
    if (LK(ctx->opcode))
3354
        gen_setlr(ctx, ctx->nip);
3355
    gen_goto_tb(ctx, 0, target);
3356
}
3357

    
3358
#define BCOND_IM  0
3359
#define BCOND_LR  1
3360
#define BCOND_CTR 2
3361

    
3362
static always_inline void gen_bcond (DisasContext *ctx, int type)
3363
{
3364
    uint32_t bo = BO(ctx->opcode);
3365
    int l1 = gen_new_label();
3366
    TCGv target;
3367

    
3368
    ctx->exception = POWERPC_EXCP_BRANCH;
3369
    if (type == BCOND_LR || type == BCOND_CTR) {
3370
        target = tcg_temp_local_new();
3371
        if (type == BCOND_CTR)
3372
            tcg_gen_mov_tl(target, cpu_ctr);
3373
        else
3374
            tcg_gen_mov_tl(target, cpu_lr);
3375
    } else {
3376
        TCGV_UNUSED(target);
3377
    }
3378
    if (LK(ctx->opcode))
3379
        gen_setlr(ctx, ctx->nip);
3380
    l1 = gen_new_label();
3381
    if ((bo & 0x4) == 0) {
3382
        /* Decrement and test CTR */
3383
        TCGv temp = tcg_temp_new();
3384
        if (unlikely(type == BCOND_CTR)) {
3385
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3386
            return;
3387
        }
3388
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3389
#if defined(TARGET_PPC64)
3390
        if (!ctx->sf_mode)
3391
            tcg_gen_ext32u_tl(temp, cpu_ctr);
3392
        else
3393
#endif
3394
            tcg_gen_mov_tl(temp, cpu_ctr);
3395
        if (bo & 0x2) {
3396
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3397
        } else {
3398
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3399
        }
3400
        tcg_temp_free(temp);
3401
    }
3402
    if ((bo & 0x10) == 0) {
3403
        /* Test CR */
3404
        uint32_t bi = BI(ctx->opcode);
3405
        uint32_t mask = 1 << (3 - (bi & 0x03));
3406
        TCGv_i32 temp = tcg_temp_new_i32();
3407

    
3408
        if (bo & 0x8) {
3409
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3410
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3411
        } else {
3412
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3413
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3414
        }
3415
        tcg_temp_free_i32(temp);
3416
    }
3417
    if (type == BCOND_IM) {
3418
        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3419
        if (likely(AA(ctx->opcode) == 0)) {
3420
            gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3421
        } else {
3422
            gen_goto_tb(ctx, 0, li);
3423
        }
3424
        gen_set_label(l1);
3425
        gen_goto_tb(ctx, 1, ctx->nip);
3426
    } else {
3427
#if defined(TARGET_PPC64)
3428
        if (!(ctx->sf_mode))
3429
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3430
        else
3431
#endif
3432
            tcg_gen_andi_tl(cpu_nip, target, ~3);
3433
        tcg_gen_exit_tb(0);
3434
        gen_set_label(l1);
3435
#if defined(TARGET_PPC64)
3436
        if (!(ctx->sf_mode))
3437
            tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
3438
        else
3439
#endif
3440
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
3441
        tcg_gen_exit_tb(0);
3442
    }
3443
}
3444

    
3445
static void gen_bc(DisasContext *ctx)
3446
{
3447
    gen_bcond(ctx, BCOND_IM);
3448
}
3449

    
3450
static void gen_bcctr(DisasContext *ctx)
3451
{
3452
    gen_bcond(ctx, BCOND_CTR);
3453
}
3454

    
3455
static void gen_bclr(DisasContext *ctx)
3456
{
3457
    gen_bcond(ctx, BCOND_LR);
3458
}
3459

    
3460
/***                      Condition register logical                       ***/
3461
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
3462
static void glue(gen_, name)(DisasContext *ctx)                                       \
3463
{                                                                             \
3464
    uint8_t bitmask;                                                          \
3465
    int sh;                                                                   \
3466
    TCGv_i32 t0, t1;                                                          \
3467
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
3468
    t0 = tcg_temp_new_i32();                                                  \
3469
    if (sh > 0)                                                               \
3470
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3471
    else if (sh < 0)                                                          \
3472
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3473
    else                                                                      \
3474
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
3475
    t1 = tcg_temp_new_i32();                                                  \
3476
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
3477
    if (sh > 0)                                                               \
3478
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3479
    else if (sh < 0)                                                          \
3480
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3481
    else                                                                      \
3482
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
3483
    tcg_op(t0, t0, t1);                                                       \
3484
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3485
    tcg_gen_andi_i32(t0, t0, bitmask);                                        \
3486
    tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask);          \
3487
    tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1);                  \
3488
    tcg_temp_free_i32(t0);                                                    \
3489
    tcg_temp_free_i32(t1);                                                    \
3490
}
3491

    
3492
/* crand */
3493
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
3494
/* crandc */
3495
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
3496
/* creqv */
3497
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
3498
/* crnand */
3499
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
3500
/* crnor */
3501
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
3502
/* cror */
3503
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
3504
/* crorc */
3505
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
3506
/* crxor */
3507
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
3508

    
3509
/* mcrf */
3510
static void gen_mcrf(DisasContext *ctx)
3511
{
3512
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
3513
}
3514

    
3515
/***                           System linkage                              ***/
3516

    
3517
/* rfi (mem_idx only) */
3518
static void gen_rfi(DisasContext *ctx)
3519
{
3520
#if defined(CONFIG_USER_ONLY)
3521
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3522
#else
3523
    /* Restore CPU state */
3524
    if (unlikely(!ctx->mem_idx)) {
3525
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3526
        return;
3527
    }
3528
    gen_helper_rfi();
3529
    gen_sync_exception(ctx);
3530
#endif
3531
}
3532

    
3533
#if defined(TARGET_PPC64)
3534
static void gen_rfid(DisasContext *ctx)
3535
{
3536
#if defined(CONFIG_USER_ONLY)
3537
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3538
#else
3539
    /* Restore CPU state */
3540
    if (unlikely(!ctx->mem_idx)) {
3541
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3542
        return;
3543
    }
3544
    gen_helper_rfid();
3545
    gen_sync_exception(ctx);
3546
#endif
3547
}
3548

    
3549
static void gen_hrfid(DisasContext *ctx)
3550
{
3551
#if defined(CONFIG_USER_ONLY)
3552
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3553
#else
3554
    /* Restore CPU state */
3555
    if (unlikely(ctx->mem_idx <= 1)) {
3556
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3557
        return;
3558
    }
3559
    gen_helper_hrfid();
3560
    gen_sync_exception(ctx);
3561
#endif
3562
}
3563
#endif
3564

    
3565
/* sc */
3566
#if defined(CONFIG_USER_ONLY)
3567
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3568
#else
3569
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3570
#endif
3571
static void gen_sc(DisasContext *ctx)
3572
{
3573
    uint32_t lev;
3574

    
3575
    lev = (ctx->opcode >> 5) & 0x7F;
3576
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
3577
}
3578

    
3579
/***                                Trap                                   ***/
3580

    
3581
/* tw */
3582
static void gen_tw(DisasContext *ctx)
3583
{
3584
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3585
    /* Update the nip since this might generate a trap exception */
3586
    gen_update_nip(ctx, ctx->nip);
3587
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3588
    tcg_temp_free_i32(t0);
3589
}
3590

    
3591
/* twi */
3592
static void gen_twi(DisasContext *ctx)
3593
{
3594
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3595
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3596
    /* Update the nip since this might generate a trap exception */
3597
    gen_update_nip(ctx, ctx->nip);
3598
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
3599
    tcg_temp_free(t0);
3600
    tcg_temp_free_i32(t1);
3601
}
3602

    
3603
#if defined(TARGET_PPC64)
3604
/* td */
3605
static void gen_td(DisasContext *ctx)
3606
{
3607
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3608
    /* Update the nip since this might generate a trap exception */
3609
    gen_update_nip(ctx, ctx->nip);
3610
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3611
    tcg_temp_free_i32(t0);
3612
}
3613

    
3614
/* tdi */
3615
static void gen_tdi(DisasContext *ctx)
3616
{
3617
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3618
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3619
    /* Update the nip since this might generate a trap exception */
3620
    gen_update_nip(ctx, ctx->nip);
3621
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
3622
    tcg_temp_free(t0);
3623
    tcg_temp_free_i32(t1);
3624
}
3625
#endif
3626

    
3627
/***                          Processor control                            ***/
3628

    
3629
/* mcrxr */
3630
static void gen_mcrxr(DisasContext *ctx)
3631
{
3632
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
3633
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3634
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
3635
}
3636

    
3637
/* mfcr mfocrf */
3638
static void gen_mfcr(DisasContext *ctx)
3639
{
3640
    uint32_t crm, crn;
3641

    
3642
    if (likely(ctx->opcode & 0x00100000)) {
3643
        crm = CRM(ctx->opcode);
3644
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
3645
            crn = ctz32 (crm);
3646
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
3647
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
3648
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3649
        }
3650
    } else {
3651
        TCGv_i32 t0 = tcg_temp_new_i32();
3652
        tcg_gen_mov_i32(t0, cpu_crf[0]);
3653
        tcg_gen_shli_i32(t0, t0, 4);
3654
        tcg_gen_or_i32(t0, t0, cpu_crf[1]);
3655
        tcg_gen_shli_i32(t0, t0, 4);
3656
        tcg_gen_or_i32(t0, t0, cpu_crf[2]);
3657
        tcg_gen_shli_i32(t0, t0, 4);
3658
        tcg_gen_or_i32(t0, t0, cpu_crf[3]);
3659
        tcg_gen_shli_i32(t0, t0, 4);
3660
        tcg_gen_or_i32(t0, t0, cpu_crf[4]);
3661
        tcg_gen_shli_i32(t0, t0, 4);
3662
        tcg_gen_or_i32(t0, t0, cpu_crf[5]);
3663
        tcg_gen_shli_i32(t0, t0, 4);
3664
        tcg_gen_or_i32(t0, t0, cpu_crf[6]);
3665
        tcg_gen_shli_i32(t0, t0, 4);
3666
        tcg_gen_or_i32(t0, t0, cpu_crf[7]);
3667
        tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
3668
        tcg_temp_free_i32(t0);
3669
    }
3670
}
3671

    
3672
/* mfmsr */
3673
static void gen_mfmsr(DisasContext *ctx)
3674
{
3675
#if defined(CONFIG_USER_ONLY)
3676
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3677
#else
3678
    if (unlikely(!ctx->mem_idx)) {
3679
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3680
        return;
3681
    }
3682
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3683
#endif
3684
}
3685

    
3686
#if 1
3687
#define SPR_NOACCESS ((void *)(-1UL))
3688
#else
3689
static void spr_noaccess (void *opaque, int sprn)
3690
{
3691
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3692
    printf("ERROR: try to access SPR %d !\n", sprn);
3693
}
3694
#define SPR_NOACCESS (&spr_noaccess)
3695
#endif
3696

    
3697
/* mfspr */
3698
static always_inline void gen_op_mfspr (DisasContext *ctx)
3699
{
3700
    void (*read_cb)(void *opaque, int gprn, int sprn);
3701
    uint32_t sprn = SPR(ctx->opcode);
3702

    
3703
#if !defined(CONFIG_USER_ONLY)
3704
    if (ctx->mem_idx == 2)
3705
        read_cb = ctx->spr_cb[sprn].hea_read;
3706
    else if (ctx->mem_idx)
3707
        read_cb = ctx->spr_cb[sprn].oea_read;
3708
    else
3709
#endif
3710
        read_cb = ctx->spr_cb[sprn].uea_read;
3711
    if (likely(read_cb != NULL)) {
3712
        if (likely(read_cb != SPR_NOACCESS)) {
3713
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3714
        } else {
3715
            /* Privilege exception */
3716
            /* This is a hack to avoid warnings when running Linux:
3717
             * this OS breaks the PowerPC virtualisation model,
3718
             * allowing userland application to read the PVR
3719
             */
3720
            if (sprn != SPR_PVR) {
3721
                qemu_log("Trying to read privileged spr %d %03x at "
3722
                            ADDRX "\n", sprn, sprn, ctx->nip);
3723
                printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
3724
                       sprn, sprn, ctx->nip);
3725
            }
3726
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3727
        }
3728
    } else {
3729
        /* Not defined */
3730
        qemu_log("Trying to read invalid spr %d %03x at "
3731
                    ADDRX "\n", sprn, sprn, ctx->nip);
3732
        printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
3733
               sprn, sprn, ctx->nip);
3734
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
3735
    }
3736
}
3737

    
3738
static void gen_mfspr(DisasContext *ctx)
3739
{
3740
    gen_op_mfspr(ctx);
3741
}
3742

    
3743
/* mftb */
3744
static void gen_mftb(DisasContext *ctx)
3745
{
3746
    gen_op_mfspr(ctx);
3747
}
3748

    
3749
/* mtcrf mtocrf*/
3750
static void gen_mtcrf(DisasContext *ctx)
3751
{
3752
    uint32_t crm, crn;
3753

    
3754
    crm = CRM(ctx->opcode);
3755
    if (likely((ctx->opcode & 0x00100000))) {
3756
        if (crm && ((crm & (crm - 1)) == 0)) {
3757
            TCGv_i32 temp = tcg_temp_new_i32();
3758
            crn = ctz32 (crm);
3759
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3760
            tcg_gen_shri_i32(temp, temp, crn * 4);
3761
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
3762
            tcg_temp_free_i32(temp);
3763
        }
3764
    } else {
3765
        TCGv_i32 temp = tcg_temp_new_i32();
3766
        tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3767
        for (crn = 0 ; crn < 8 ; crn++) {
3768
            if (crm & (1 << crn)) {
3769
                    tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
3770
                    tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3771
            }
3772
        }
3773
        tcg_temp_free_i32(temp);
3774
    }
3775
}
3776

    
3777
/* mtmsr */
3778
#if defined(TARGET_PPC64)
3779
static void gen_mtmsrd(DisasContext *ctx)
3780
{
3781
#if defined(CONFIG_USER_ONLY)
3782
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3783
#else
3784
    if (unlikely(!ctx->mem_idx)) {
3785
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3786
        return;
3787
    }
3788
    if (ctx->opcode & 0x00010000) {
3789
        /* Special form that does not need any synchronisation */
3790
        TCGv t0 = tcg_temp_new();
3791
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3792
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3793
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3794
        tcg_temp_free(t0);
3795
    } else {
3796
        /* XXX: we need to update nip before the store
3797
         *      if we enter power saving mode, we will exit the loop
3798
         *      directly from ppc_store_msr
3799
         */
3800
        gen_update_nip(ctx, ctx->nip);
3801
        gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3802
        /* Must stop the translation as machine state (may have) changed */
3803
        /* Note that mtmsr is not always defined as context-synchronizing */
3804
        gen_stop_exception(ctx);
3805
    }
3806
#endif
3807
}
3808
#endif
3809

    
3810
static void gen_mtmsr(DisasContext *ctx)
3811
{
3812
#if defined(CONFIG_USER_ONLY)
3813
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3814
#else
3815
    if (unlikely(!ctx->mem_idx)) {
3816
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3817
        return;
3818
    }
3819
    if (ctx->opcode & 0x00010000) {
3820
        /* Special form that does not need any synchronisation */
3821
        TCGv t0 = tcg_temp_new();
3822
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3823
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3824
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3825
        tcg_temp_free(t0);
3826
    } else {
3827
        /* XXX: we need to update nip before the store
3828
         *      if we enter power saving mode, we will exit the loop
3829
         *      directly from ppc_store_msr
3830
         */
3831
        gen_update_nip(ctx, ctx->nip);
3832
#if defined(TARGET_PPC64)
3833
        if (!ctx->sf_mode) {
3834
            TCGv t0 = tcg_temp_new();
3835
            TCGv t1 = tcg_temp_new();
3836
            tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
3837
            tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
3838
            tcg_gen_or_tl(t0, t0, t1);
3839
            tcg_temp_free(t1);
3840
            gen_helper_store_msr(t0);
3841
            tcg_temp_free(t0);
3842
        } else
3843
#endif
3844
            gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3845
        /* Must stop the translation as machine state (may have) changed */
3846
        /* Note that mtmsr is not always defined as context-synchronizing */
3847
        gen_stop_exception(ctx);
3848
    }
3849
#endif
3850
}
3851

    
3852
/* mtspr */
3853
static void gen_mtspr(DisasContext *ctx)
3854
{
3855
    void (*write_cb)(void *opaque, int sprn, int gprn);
3856
    uint32_t sprn = SPR(ctx->opcode);
3857

    
3858
#if !defined(CONFIG_USER_ONLY)
3859
    if (ctx->mem_idx == 2)
3860
        write_cb = ctx->spr_cb[sprn].hea_write;
3861
    else if (ctx->mem_idx)
3862
        write_cb = ctx->spr_cb[sprn].oea_write;
3863
    else
3864
#endif
3865
        write_cb = ctx->spr_cb[sprn].uea_write;
3866
    if (likely(write_cb != NULL)) {
3867
        if (likely(write_cb != SPR_NOACCESS)) {
3868
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
3869
        } else {
3870
            /* Privilege exception */
3871
            qemu_log("Trying to write privileged spr %d %03x at "
3872
                        ADDRX "\n", sprn, sprn, ctx->nip);
3873
            printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
3874
                   sprn, sprn, ctx->nip);
3875
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3876
        }
3877
    } else {
3878
        /* Not defined */
3879
        qemu_log("Trying to write invalid spr %d %03x at "
3880
                    ADDRX "\n", sprn, sprn, ctx->nip);
3881
        printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
3882
               sprn, sprn, ctx->nip);
3883
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
3884
    }
3885
}
3886

    
3887
/***                         Cache management                              ***/
3888

    
3889
/* dcbf */
3890
static void gen_dcbf(DisasContext *ctx)
3891
{
3892
    /* XXX: specification says this is treated as a load by the MMU */
3893
    TCGv t0;
3894
    gen_set_access_type(ctx, ACCESS_CACHE);
3895
    t0 = tcg_temp_new();
3896
    gen_addr_reg_index(ctx, t0);
3897
    gen_qemu_ld8u(ctx, t0, t0);
3898
    tcg_temp_free(t0);
3899
}
3900

    
3901
/* dcbi (Supervisor only) */
3902
static void gen_dcbi(DisasContext *ctx)
3903
{
3904
#if defined(CONFIG_USER_ONLY)
3905
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3906
#else
3907
    TCGv EA, val;
3908
    if (unlikely(!ctx->mem_idx)) {
3909
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3910
        return;
3911
    }
3912
    EA = tcg_temp_new();
3913
    gen_set_access_type(ctx, ACCESS_CACHE);
3914
    gen_addr_reg_index(ctx, EA);
3915
    val = tcg_temp_new();
3916
    /* XXX: specification says this should be treated as a store by the MMU */
3917
    gen_qemu_ld8u(ctx, val, EA);
3918
    gen_qemu_st8(ctx, val, EA);
3919
    tcg_temp_free(val);
3920
    tcg_temp_free(EA);
3921
#endif
3922
}
3923

    
3924
/* dcdst */
3925
static void gen_dcbst(DisasContext *ctx)
3926
{
3927
    /* XXX: specification say this is treated as a load by the MMU */
3928
    TCGv t0;
3929
    gen_set_access_type(ctx, ACCESS_CACHE);
3930
    t0 = tcg_temp_new();
3931
    gen_addr_reg_index(ctx, t0);
3932
    gen_qemu_ld8u(ctx, t0, t0);
3933
    tcg_temp_free(t0);
3934
}
3935

    
3936
/* dcbt */
3937
static void gen_dcbt(DisasContext *ctx)
3938
{
3939
    /* interpreted as no-op */
3940
    /* XXX: specification say this is treated as a load by the MMU
3941
     *      but does not generate any exception
3942
     */
3943
}
3944

    
3945
/* dcbtst */
3946
static void gen_dcbtst(DisasContext *ctx)
3947
{
3948
    /* interpreted as no-op */
3949
    /* XXX: specification say this is treated as a load by the MMU
3950
     *      but does not generate any exception
3951
     */
3952
}
3953

    
3954
/* dcbz */
3955
static void gen_dcbz(DisasContext *ctx)
3956
{
3957
    TCGv t0;
3958
    gen_set_access_type(ctx, ACCESS_CACHE);
3959
    /* NIP cannot be restored if the memory exception comes from an helper */
3960
    gen_update_nip(ctx, ctx->nip - 4);
3961
    t0 = tcg_temp_new();
3962
    gen_addr_reg_index(ctx, t0);
3963
    gen_helper_dcbz(t0);
3964
    tcg_temp_free(t0);
3965
}
3966

    
3967
static void gen_dcbz_970(DisasContext *ctx)
3968
{
3969
    TCGv t0;
3970
    gen_set_access_type(ctx, ACCESS_CACHE);
3971
    /* NIP cannot be restored if the memory exception comes from an helper */
3972
    gen_update_nip(ctx, ctx->nip - 4);
3973
    t0 = tcg_temp_new();
3974
    gen_addr_reg_index(ctx, t0);
3975
    if (ctx->opcode & 0x00200000)
3976
        gen_helper_dcbz(t0);
3977
    else
3978
        gen_helper_dcbz_970(t0);
3979
    tcg_temp_free(t0);
3980
}
3981

    
3982
/* dst / dstt */
3983
static void gen_dst(DisasContext *ctx)
3984
{
3985
    if (rA(ctx->opcode) == 0) {
3986
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3987
    } else {
3988
        /* interpreted as no-op */
3989
    }
3990
}
3991

    
3992
/* dstst /dststt */
3993
static void gen_dstst(DisasContext *ctx)
3994
{
3995
    if (rA(ctx->opcode) == 0) {
3996
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3997
    } else {
3998
        /* interpreted as no-op */
3999
    }
4000

    
4001
}
4002

    
4003
/* dss / dssall */
4004
static void gen_dss(DisasContext *ctx)
4005
{
4006
    /* interpreted as no-op */
4007
}
4008

    
4009
/* icbi */
4010
static void gen_icbi(DisasContext *ctx)
4011
{
4012
    TCGv t0;
4013
    gen_set_access_type(ctx, ACCESS_CACHE);
4014
    /* NIP cannot be restored if the memory exception comes from an helper */
4015
    gen_update_nip(ctx, ctx->nip - 4);
4016
    t0 = tcg_temp_new();
4017
    gen_addr_reg_index(ctx, t0);
4018
    gen_helper_icbi(t0);
4019
    tcg_temp_free(t0);
4020
}
4021

    
4022
/* Optional: */
4023
/* dcba */
4024
static void gen_dcba(DisasContext *ctx)
4025
{
4026
    /* interpreted as no-op */
4027
    /* XXX: specification say this is treated as a store by the MMU
4028
     *      but does not generate any exception
4029
     */
4030
}
4031

    
4032
/***                    Segment register manipulation                      ***/
4033
/* Supervisor only: */
4034

    
4035
/* mfsr */
4036
static void gen_mfsr(DisasContext *ctx)
4037
{
4038
#if defined(CONFIG_USER_ONLY)
4039
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4040
#else
4041
    TCGv t0;
4042
    if (unlikely(!ctx->mem_idx)) {
4043
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4044
        return;
4045
    }
4046
    t0 = tcg_const_tl(SR(ctx->opcode));
4047
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4048
    tcg_temp_free(t0);
4049
#endif
4050
}
4051

    
4052
/* mfsrin */
4053
static void gen_mfsrin(DisasContext *ctx)
4054
{
4055
#if defined(CONFIG_USER_ONLY)
4056
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4057
#else
4058
    TCGv t0;
4059
    if (unlikely(!ctx->mem_idx)) {
4060
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4061
        return;
4062
    }
4063
    t0 = tcg_temp_new();
4064
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4065
    tcg_gen_andi_tl(t0, t0, 0xF);
4066
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4067
    tcg_temp_free(t0);
4068
#endif
4069
}
4070

    
4071
/* mtsr */
4072
static void gen_mtsr(DisasContext *ctx)
4073
{
4074
#if defined(CONFIG_USER_ONLY)
4075
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4076
#else
4077
    TCGv t0;
4078
    if (unlikely(!ctx->mem_idx)) {
4079
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4080
        return;
4081
    }
4082
    t0 = tcg_const_tl(SR(ctx->opcode));
4083
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4084
    tcg_temp_free(t0);
4085
#endif
4086
}
4087

    
4088
/* mtsrin */
4089
static void gen_mtsrin(DisasContext *ctx)
4090
{
4091
#if defined(CONFIG_USER_ONLY)
4092
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4093
#else
4094
    TCGv t0;
4095
    if (unlikely(!ctx->mem_idx)) {
4096
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4097
        return;
4098
    }
4099
    t0 = tcg_temp_new();
4100
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4101
    tcg_gen_andi_tl(t0, t0, 0xF);
4102
    gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
4103
    tcg_temp_free(t0);
4104
#endif
4105
}
4106

    
4107
#if defined(TARGET_PPC64)
4108
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
4109

    
4110
/* mfsr */
4111
static void gen_mfsr_64b(DisasContext *ctx)
4112
{
4113
#if defined(CONFIG_USER_ONLY)
4114
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4115
#else
4116
    TCGv t0;
4117
    if (unlikely(!ctx->mem_idx)) {
4118
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4119
        return;
4120
    }
4121
    t0 = tcg_const_tl(SR(ctx->opcode));
4122
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4123
    tcg_temp_free(t0);
4124
#endif
4125
}
4126

    
4127
/* mfsrin */
4128
static void gen_mfsrin_64b(DisasContext *ctx)
4129
{
4130
#if defined(CONFIG_USER_ONLY)
4131
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4132
#else
4133
    TCGv t0;
4134
    if (unlikely(!ctx->mem_idx)) {
4135
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4136
        return;
4137
    }
4138
    t0 = tcg_temp_new();
4139
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4140
    tcg_gen_andi_tl(t0, t0, 0xF);
4141
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4142
    tcg_temp_free(t0);
4143
#endif
4144
}
4145

    
4146
/* mtsr */
4147
static void gen_mtsr_64b(DisasContext *ctx)
4148
{
4149
#if defined(CONFIG_USER_ONLY)
4150
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4151
#else
4152
    TCGv t0;
4153
    if (unlikely(!ctx->mem_idx)) {
4154
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4155
        return;
4156
    }
4157
    t0 = tcg_const_tl(SR(ctx->opcode));
4158
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4159
    tcg_temp_free(t0);
4160
#endif
4161
}
4162

    
4163
/* mtsrin */
4164
static void gen_mtsrin_64b(DisasContext *ctx)
4165
{
4166
#if defined(CONFIG_USER_ONLY)
4167
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4168
#else
4169
    TCGv t0;
4170
    if (unlikely(!ctx->mem_idx)) {
4171
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4172
        return;
4173
    }
4174
    t0 = tcg_temp_new();
4175
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4176
    tcg_gen_andi_tl(t0, t0, 0xF);
4177
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4178
    tcg_temp_free(t0);
4179
#endif
4180
}
4181

    
4182
/* slbmte */
4183
static void gen_slbmte(DisasContext *ctx)
4184
{
4185
#if defined(CONFIG_USER_ONLY)
4186
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4187
#else
4188
    if (unlikely(!ctx->mem_idx)) {
4189
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4190
        return;
4191
    }
4192
    gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
4193
#endif
4194
}
4195

    
4196
#endif /* defined(TARGET_PPC64) */
4197

    
4198
/***                      Lookaside buffer management                      ***/
4199
/* Optional & mem_idx only: */
4200

    
4201
/* tlbia */
4202
static void gen_tlbia(DisasContext *ctx)
4203
{
4204
#if defined(CONFIG_USER_ONLY)
4205
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4206
#else
4207
    if (unlikely(!ctx->mem_idx)) {
4208
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4209
        return;
4210
    }
4211
    gen_helper_tlbia();
4212
#endif
4213
}
4214

    
4215
/* tlbiel */
4216
static void gen_tlbiel(DisasContext *ctx)
4217
{
4218
#if defined(CONFIG_USER_ONLY)
4219
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4220
#else
4221
    if (unlikely(!ctx->mem_idx)) {
4222
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4223
        return;
4224
    }
4225
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4226
#endif
4227
}
4228

    
4229
/* tlbie */
4230
static void gen_tlbie(DisasContext *ctx)
4231
{
4232
#if defined(CONFIG_USER_ONLY)
4233
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4234
#else
4235
    if (unlikely(!ctx->mem_idx)) {
4236
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4237
        return;
4238
    }
4239
#if defined(TARGET_PPC64)
4240
    if (!ctx->sf_mode) {
4241
        TCGv t0 = tcg_temp_new();
4242
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4243
        gen_helper_tlbie(t0);
4244
        tcg_temp_free(t0);
4245
    } else
4246
#endif
4247
        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4248
#endif
4249
}
4250

    
4251
/* tlbsync */
4252
static void gen_tlbsync(DisasContext *ctx)
4253
{
4254
#if defined(CONFIG_USER_ONLY)
4255
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4256
#else
4257
    if (unlikely(!ctx->mem_idx)) {
4258
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4259
        return;
4260
    }
4261
    /* This has no effect: it should ensure that all previous
4262
     * tlbie have completed
4263
     */
4264
    gen_stop_exception(ctx);
4265
#endif
4266
}
4267

    
4268
#if defined(TARGET_PPC64)
4269
/* slbia */
4270
static void gen_slbia(DisasContext *ctx)
4271
{
4272
#if defined(CONFIG_USER_ONLY)
4273
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4274
#else
4275
    if (unlikely(!ctx->mem_idx)) {
4276
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4277
        return;
4278
    }
4279
    gen_helper_slbia();
4280
#endif
4281
}
4282

    
4283
/* slbie */
4284
static void gen_slbie(DisasContext *ctx)
4285
{
4286
#if defined(CONFIG_USER_ONLY)
4287
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4288
#else
4289
    if (unlikely(!ctx->mem_idx)) {
4290
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4291
        return;
4292
    }
4293
    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
4294
#endif
4295
}
4296
#endif
4297

    
4298
/***                              External control                         ***/
4299
/* Optional: */
4300

    
4301
/* eciwx */
4302
static void gen_eciwx(DisasContext *ctx)
4303
{
4304
    TCGv t0;
4305
    /* Should check EAR[E] ! */
4306
    gen_set_access_type(ctx, ACCESS_EXT);
4307
    t0 = tcg_temp_new();
4308
    gen_addr_reg_index(ctx, t0);
4309
    gen_check_align(ctx, t0, 0x03);
4310
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4311
    tcg_temp_free(t0);
4312
}
4313

    
4314
/* ecowx */
4315
static void gen_ecowx(DisasContext *ctx)
4316
{
4317
    TCGv t0;
4318
    /* Should check EAR[E] ! */
4319
    gen_set_access_type(ctx, ACCESS_EXT);
4320
    t0 = tcg_temp_new();
4321
    gen_addr_reg_index(ctx, t0);
4322
    gen_check_align(ctx, t0, 0x03);
4323
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4324
    tcg_temp_free(t0);
4325
}
4326

    
4327
/* PowerPC 601 specific instructions */
4328

    
4329
/* abs - abs. */
4330
static void gen_abs(DisasContext *ctx)
4331
{
4332
    int l1 = gen_new_label();
4333
    int l2 = gen_new_label();
4334
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4335
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4336
    tcg_gen_br(l2);
4337
    gen_set_label(l1);
4338
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4339
    gen_set_label(l2);
4340
    if (unlikely(Rc(ctx->opcode) != 0))
4341
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4342
}
4343

    
4344
/* abso - abso. */
4345
static void gen_abso(DisasContext *ctx)
4346
{
4347
    int l1 = gen_new_label();
4348
    int l2 = gen_new_label();
4349
    int l3 = gen_new_label();
4350
    /* Start with XER OV disabled, the most likely case */
4351
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4352
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4353
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4354
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4355
    tcg_gen_br(l2);
4356
    gen_set_label(l1);
4357
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4358
    tcg_gen_br(l3);
4359
    gen_set_label(l2);
4360
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4361
    gen_set_label(l3);
4362
    if (unlikely(Rc(ctx->opcode) != 0))
4363
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4364
}
4365

    
4366
/* clcs */
4367
static void gen_clcs(DisasContext *ctx)
4368
{
4369
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4370
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
4371
    tcg_temp_free_i32(t0);
4372
    /* Rc=1 sets CR0 to an undefined state */
4373
}
4374

    
4375
/* div - div. */
4376
static void gen_div(DisasContext *ctx)
4377
{
4378
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4379
    if (unlikely(Rc(ctx->opcode) != 0))
4380
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4381
}
4382

    
4383
/* divo - divo. */
4384
static void gen_divo(DisasContext *ctx)
4385
{
4386
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4387
    if (unlikely(Rc(ctx->opcode) != 0))
4388
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4389
}
4390

    
4391
/* divs - divs. */
4392
static void gen_divs(DisasContext *ctx)
4393
{
4394
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4395
    if (unlikely(Rc(ctx->opcode) != 0))
4396
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4397
}
4398

    
4399
/* divso - divso. */
4400
static void gen_divso(DisasContext *ctx)
4401
{
4402
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4403
    if (unlikely(Rc(ctx->opcode) != 0))
4404
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4405
}
4406

    
4407
/* doz - doz. */
4408
static void gen_doz(DisasContext *ctx)
4409
{
4410
    int l1 = gen_new_label();
4411
    int l2 = gen_new_label();
4412
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4413
    tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4414
    tcg_gen_br(l2);
4415
    gen_set_label(l1);
4416
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4417
    gen_set_label(l2);
4418
    if (unlikely(Rc(ctx->opcode) != 0))
4419
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4420
}
4421

    
4422
/* dozo - dozo. */
4423
static void gen_dozo(DisasContext *ctx)
4424
{
4425
    int l1 = gen_new_label();
4426
    int l2 = gen_new_label();
4427
    TCGv t0 = tcg_temp_new();
4428
    TCGv t1 = tcg_temp_new();
4429
    TCGv t2 = tcg_temp_new();
4430
    /* Start with XER OV disabled, the most likely case */
4431
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4432
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4433
    tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4434
    tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4435
    tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4436
    tcg_gen_andc_tl(t1, t1, t2);
4437
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4438
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4439
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4440
    tcg_gen_br(l2);
4441
    gen_set_label(l1);
4442
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4443
    gen_set_label(l2);
4444
    tcg_temp_free(t0);
4445
    tcg_temp_free(t1);
4446
    tcg_temp_free(t2);
4447
    if (unlikely(Rc(ctx->opcode) != 0))
4448
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4449
}
4450

    
4451
/* dozi */
4452
static void gen_dozi(DisasContext *ctx)
4453
{
4454
    target_long simm = SIMM(ctx->opcode);
4455
    int l1 = gen_new_label();
4456
    int l2 = gen_new_label();
4457
    tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4458
    tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4459
    tcg_gen_br(l2);
4460
    gen_set_label(l1);
4461
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4462
    gen_set_label(l2);
4463
    if (unlikely(Rc(ctx->opcode) != 0))
4464
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4465
}
4466

    
4467
/* lscbx - lscbx. */
4468
static void gen_lscbx(DisasContext *ctx)
4469
{
4470
    TCGv t0 = tcg_temp_new();
4471
    TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4472
    TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4473
    TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
4474

    
4475
    gen_addr_reg_index(ctx, t0);
4476
    /* NIP cannot be restored if the memory exception comes from an helper */
4477
    gen_update_nip(ctx, ctx->nip - 4);
4478
    gen_helper_lscbx(t0, t0, t1, t2, t3);
4479
    tcg_temp_free_i32(t1);
4480
    tcg_temp_free_i32(t2);
4481
    tcg_temp_free_i32(t3);
4482
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4483
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4484
    if (unlikely(Rc(ctx->opcode) != 0))
4485
        gen_set_Rc0(ctx, t0);
4486
    tcg_temp_free(t0);
4487
}
4488

    
4489
/* maskg - maskg. */
4490
static void gen_maskg(DisasContext *ctx)
4491
{
4492
    int l1 = gen_new_label();
4493
    TCGv t0 = tcg_temp_new();
4494
    TCGv t1 = tcg_temp_new();
4495
    TCGv t2 = tcg_temp_new();
4496
    TCGv t3 = tcg_temp_new();
4497
    tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4498
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4499
    tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4500
    tcg_gen_addi_tl(t2, t0, 1);
4501
    tcg_gen_shr_tl(t2, t3, t2);
4502
    tcg_gen_shr_tl(t3, t3, t1);
4503
    tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4504
    tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4505
    tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4506
    gen_set_label(l1);
4507
    tcg_temp_free(t0);
4508
    tcg_temp_free(t1);
4509
    tcg_temp_free(t2);
4510
    tcg_temp_free(t3);
4511
    if (unlikely(Rc(ctx->opcode) != 0))
4512
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4513
}
4514

    
4515
/* maskir - maskir. */
4516
static void gen_maskir(DisasContext *ctx)
4517
{
4518
    TCGv t0 = tcg_temp_new();
4519
    TCGv t1 = tcg_temp_new();
4520
    tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4521
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4522
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4523
    tcg_temp_free(t0);
4524
    tcg_temp_free(t1);
4525
    if (unlikely(Rc(ctx->opcode) != 0))
4526
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4527
}
4528

    
4529
/* mul - mul. */
4530
static void gen_mul(DisasContext *ctx)
4531
{
4532
    TCGv_i64 t0 = tcg_temp_new_i64();
4533
    TCGv_i64 t1 = tcg_temp_new_i64();
4534
    TCGv t2 = tcg_temp_new();
4535
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4536
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4537
    tcg_gen_mul_i64(t0, t0, t1);
4538
    tcg_gen_trunc_i64_tl(t2, t0);
4539
    gen_store_spr(SPR_MQ, t2);
4540
    tcg_gen_shri_i64(t1, t0, 32);
4541
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4542
    tcg_temp_free_i64(t0);
4543
    tcg_temp_free_i64(t1);
4544
    tcg_temp_free(t2);
4545
    if (unlikely(Rc(ctx->opcode) != 0))
4546
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4547
}
4548

    
4549
/* mulo - mulo. */
4550
static void gen_mulo(DisasContext *ctx)
4551
{
4552
    int l1 = gen_new_label();
4553
    TCGv_i64 t0 = tcg_temp_new_i64();
4554
    TCGv_i64 t1 = tcg_temp_new_i64();
4555
    TCGv t2 = tcg_temp_new();
4556
    /* Start with XER OV disabled, the most likely case */
4557
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4558
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4559
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4560
    tcg_gen_mul_i64(t0, t0, t1);
4561
    tcg_gen_trunc_i64_tl(t2, t0);
4562
    gen_store_spr(SPR_MQ, t2);
4563
    tcg_gen_shri_i64(t1, t0, 32);
4564
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4565
    tcg_gen_ext32s_i64(t1, t0);
4566
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4567
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4568
    gen_set_label(l1);
4569
    tcg_temp_free_i64(t0);
4570
    tcg_temp_free_i64(t1);
4571
    tcg_temp_free(t2);
4572
    if (unlikely(Rc(ctx->opcode) != 0))
4573
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4574
}
4575

    
4576
/* nabs - nabs. */
4577
static void gen_nabs(DisasContext *ctx)
4578
{
4579
    int l1 = gen_new_label();
4580
    int l2 = gen_new_label();
4581
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4582
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4583
    tcg_gen_br(l2);
4584
    gen_set_label(l1);
4585
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4586
    gen_set_label(l2);
4587
    if (unlikely(Rc(ctx->opcode) != 0))
4588
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4589
}
4590

    
4591
/* nabso - nabso. */
4592
static void gen_nabso(DisasContext *ctx)
4593
{
4594
    int l1 = gen_new_label();
4595
    int l2 = gen_new_label();
4596
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4597
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4598
    tcg_gen_br(l2);
4599
    gen_set_label(l1);
4600
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4601
    gen_set_label(l2);
4602
    /* nabs never overflows */
4603
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4604
    if (unlikely(Rc(ctx->opcode) != 0))
4605
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4606
}
4607

    
4608
/* rlmi - rlmi. */
4609
static void gen_rlmi(DisasContext *ctx)
4610
{
4611
    uint32_t mb = MB(ctx->opcode);
4612
    uint32_t me = ME(ctx->opcode);
4613
    TCGv t0 = tcg_temp_new();
4614
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4615
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4616
    tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4617
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4618
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4619
    tcg_temp_free(t0);
4620
    if (unlikely(Rc(ctx->opcode) != 0))
4621
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4622
}
4623

    
4624
/* rrib - rrib. */
4625
static void gen_rrib(DisasContext *ctx)
4626
{
4627
    TCGv t0 = tcg_temp_new();
4628
    TCGv t1 = tcg_temp_new();
4629
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4630
    tcg_gen_movi_tl(t1, 0x80000000);
4631
    tcg_gen_shr_tl(t1, t1, t0);
4632
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4633
    tcg_gen_and_tl(t0, t0, t1);
4634
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4635
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4636
    tcg_temp_free(t0);
4637
    tcg_temp_free(t1);
4638
    if (unlikely(Rc(ctx->opcode) != 0))
4639
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4640
}
4641

    
4642
/* sle - sle. */
4643
static void gen_sle(DisasContext *ctx)
4644
{
4645
    TCGv t0 = tcg_temp_new();
4646
    TCGv t1 = tcg_temp_new();
4647
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4648
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4649
    tcg_gen_subfi_tl(t1, 32, t1);
4650
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4651
    tcg_gen_or_tl(t1, t0, t1);
4652
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4653
    gen_store_spr(SPR_MQ, t1);
4654
    tcg_temp_free(t0);
4655
    tcg_temp_free(t1);
4656
    if (unlikely(Rc(ctx->opcode) != 0))
4657
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4658
}
4659

    
4660
/* sleq - sleq. */
4661
static void gen_sleq(DisasContext *ctx)
4662
{
4663
    TCGv t0 = tcg_temp_new();
4664
    TCGv t1 = tcg_temp_new();
4665
    TCGv t2 = tcg_temp_new();
4666
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4667
    tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4668
    tcg_gen_shl_tl(t2, t2, t0);
4669
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4670
    gen_load_spr(t1, SPR_MQ);
4671
    gen_store_spr(SPR_MQ, t0);
4672
    tcg_gen_and_tl(t0, t0, t2);
4673
    tcg_gen_andc_tl(t1, t1, t2);
4674
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4675
    tcg_temp_free(t0);
4676
    tcg_temp_free(t1);
4677
    tcg_temp_free(t2);
4678
    if (unlikely(Rc(ctx->opcode) != 0))
4679
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4680
}
4681

    
4682
/* sliq - sliq. */
4683
static void gen_sliq(DisasContext *ctx)
4684
{
4685
    int sh = SH(ctx->opcode);
4686
    TCGv t0 = tcg_temp_new();
4687
    TCGv t1 = tcg_temp_new();
4688
    tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4689
    tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4690
    tcg_gen_or_tl(t1, t0, t1);
4691
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4692
    gen_store_spr(SPR_MQ, t1);
4693
    tcg_temp_free(t0);
4694
    tcg_temp_free(t1);
4695
    if (unlikely(Rc(ctx->opcode) != 0))
4696
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4697
}
4698

    
4699
/* slliq - slliq. */
4700
static void gen_slliq(DisasContext *ctx)
4701
{
4702
    int sh = SH(ctx->opcode);
4703
    TCGv t0 = tcg_temp_new();
4704
    TCGv t1 = tcg_temp_new();
4705
    tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4706
    gen_load_spr(t1, SPR_MQ);
4707
    gen_store_spr(SPR_MQ, t0);
4708
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU << sh));
4709
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
4710
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4711
    tcg_temp_free(t0);
4712
    tcg_temp_free(t1);
4713
    if (unlikely(Rc(ctx->opcode) != 0))
4714
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4715
}
4716

    
4717
/* sllq - sllq. */
4718
static void gen_sllq(DisasContext *ctx)
4719
{
4720
    int l1 = gen_new_label();
4721
    int l2 = gen_new_label();
4722
    TCGv t0 = tcg_temp_local_new();
4723
    TCGv t1 = tcg_temp_local_new();
4724
    TCGv t2 = tcg_temp_local_new();
4725
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4726
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4727
    tcg_gen_shl_tl(t1, t1, t2);
4728
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4729
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4730
    gen_load_spr(t0, SPR_MQ);
4731
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4732
    tcg_gen_br(l2);
4733
    gen_set_label(l1);
4734
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4735
    gen_load_spr(t2, SPR_MQ);
4736
    tcg_gen_andc_tl(t1, t2, t1);
4737
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4738
    gen_set_label(l2);
4739
    tcg_temp_free(t0);
4740
    tcg_temp_free(t1);
4741
    tcg_temp_free(t2);
4742
    if (unlikely(Rc(ctx->opcode) != 0))
4743
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4744
}
4745

    
4746
/* slq - slq. */
4747
static void gen_slq(DisasContext *ctx)
4748
{
4749
    int l1 = gen_new_label();
4750
    TCGv t0 = tcg_temp_new();
4751
    TCGv t1 = tcg_temp_new();
4752
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4753
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4754
    tcg_gen_subfi_tl(t1, 32, t1);
4755
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4756
    tcg_gen_or_tl(t1, t0, t1);
4757
    gen_store_spr(SPR_MQ, t1);
4758
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4759
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4760
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4761
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4762
    gen_set_label(l1);
4763
    tcg_temp_free(t0);
4764
    tcg_temp_free(t1);
4765
    if (unlikely(Rc(ctx->opcode) != 0))
4766
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4767
}
4768

    
4769
/* sraiq - sraiq. */
4770
static void gen_sraiq(DisasContext *ctx)
4771
{
4772
    int sh = SH(ctx->opcode);
4773
    int l1 = gen_new_label();
4774
    TCGv t0 = tcg_temp_new();
4775
    TCGv t1 = tcg_temp_new();
4776
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4777
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4778
    tcg_gen_or_tl(t0, t0, t1);
4779
    gen_store_spr(SPR_MQ, t0);
4780
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4781
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4782
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4783
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4784
    gen_set_label(l1);
4785
    tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
4786
    tcg_temp_free(t0);
4787
    tcg_temp_free(t1);
4788
    if (unlikely(Rc(ctx->opcode) != 0))
4789
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4790
}
4791

    
4792
/* sraq - sraq. */
4793
static void gen_sraq(DisasContext *ctx)
4794
{
4795
    int l1 = gen_new_label();
4796
    int l2 = gen_new_label();
4797
    TCGv t0 = tcg_temp_new();
4798
    TCGv t1 = tcg_temp_local_new();
4799
    TCGv t2 = tcg_temp_local_new();
4800
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4801
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4802
    tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
4803
    tcg_gen_subfi_tl(t2, 32, t2);
4804
    tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
4805
    tcg_gen_or_tl(t0, t0, t2);
4806
    gen_store_spr(SPR_MQ, t0);
4807
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4808
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
4809
    tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
4810
    tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
4811
    gen_set_label(l1);
4812
    tcg_temp_free(t0);
4813
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4814
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4815
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4816
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4817
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4818
    gen_set_label(l2);
4819
    tcg_temp_free(t1);
4820
    tcg_temp_free(t2);
4821
    if (unlikely(Rc(ctx->opcode) != 0))
4822
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4823
}
4824

    
4825
/* sre - sre. */
4826
static void gen_sre(DisasContext *ctx)
4827
{
4828
    TCGv t0 = tcg_temp_new();
4829
    TCGv t1 = tcg_temp_new();
4830
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4831
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4832
    tcg_gen_subfi_tl(t1, 32, t1);
4833
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4834
    tcg_gen_or_tl(t1, t0, t1);
4835
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4836
    gen_store_spr(SPR_MQ, t1);
4837
    tcg_temp_free(t0);
4838
    tcg_temp_free(t1);
4839
    if (unlikely(Rc(ctx->opcode) != 0))
4840
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4841
}
4842

    
4843
/* srea - srea. */
4844
static void gen_srea(DisasContext *ctx)
4845
{
4846
    TCGv t0 = tcg_temp_new();
4847
    TCGv t1 = tcg_temp_new();
4848
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4849
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4850
    gen_store_spr(SPR_MQ, t0);
4851
    tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
4852
    tcg_temp_free(t0);
4853
    tcg_temp_free(t1);
4854
    if (unlikely(Rc(ctx->opcode) != 0))
4855
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4856
}
4857

    
4858
/* sreq */
4859
static void gen_sreq(DisasContext *ctx)
4860
{
4861
    TCGv t0 = tcg_temp_new();
4862
    TCGv t1 = tcg_temp_new();
4863
    TCGv t2 = tcg_temp_new();
4864
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4865
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4866
    tcg_gen_shr_tl(t1, t1, t0);
4867
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4868
    gen_load_spr(t2, SPR_MQ);
4869
    gen_store_spr(SPR_MQ, t0);
4870
    tcg_gen_and_tl(t0, t0, t1);
4871
    tcg_gen_andc_tl(t2, t2, t1);
4872
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4873
    tcg_temp_free(t0);
4874
    tcg_temp_free(t1);
4875
    tcg_temp_free(t2);
4876
    if (unlikely(Rc(ctx->opcode) != 0))
4877
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4878
}
4879

    
4880
/* sriq */
4881
static void gen_sriq(DisasContext *ctx)
4882
{
4883
    int sh = SH(ctx->opcode);
4884
    TCGv t0 = tcg_temp_new();
4885
    TCGv t1 = tcg_temp_new();
4886
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4887
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4888
    tcg_gen_or_tl(t1, t0, t1);
4889
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4890
    gen_store_spr(SPR_MQ, t1);
4891
    tcg_temp_free(t0);
4892
    tcg_temp_free(t1);
4893
    if (unlikely(Rc(ctx->opcode) != 0))
4894
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4895
}
4896

    
4897
/* srliq */
4898
static void gen_srliq(DisasContext *ctx)
4899
{
4900
    int sh = SH(ctx->opcode);
4901
    TCGv t0 = tcg_temp_new();
4902
    TCGv t1 = tcg_temp_new();
4903
    tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4904
    gen_load_spr(t1, SPR_MQ);
4905
    gen_store_spr(SPR_MQ, t0);
4906
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU >> sh));
4907
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
4908
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4909
    tcg_temp_free(t0);
4910
    tcg_temp_free(t1);
4911
    if (unlikely(Rc(ctx->opcode) != 0))
4912
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4913
}
4914

    
4915
/* srlq */
4916
static void gen_srlq(DisasContext *ctx)
4917
{
4918
    int l1 = gen_new_label();
4919
    int l2 = gen_new_label();
4920
    TCGv t0 = tcg_temp_local_new();
4921
    TCGv t1 = tcg_temp_local_new();
4922
    TCGv t2 = tcg_temp_local_new();
4923
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4924
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4925
    tcg_gen_shr_tl(t2, t1, t2);
4926
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4927
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4928
    gen_load_spr(t0, SPR_MQ);
4929
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4930
    tcg_gen_br(l2);
4931
    gen_set_label(l1);
4932
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4933
    tcg_gen_and_tl(t0, t0, t2);
4934
    gen_load_spr(t1, SPR_MQ);
4935
    tcg_gen_andc_tl(t1, t1, t2);
4936
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4937
    gen_set_label(l2);
4938
    tcg_temp_free(t0);
4939
    tcg_temp_free(t1);
4940
    tcg_temp_free(t2);
4941
    if (unlikely(Rc(ctx->opcode) != 0))
4942
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4943
}
4944

    
4945
/* srq */
4946
static void gen_srq(DisasContext *ctx)
4947
{
4948
    int l1 = gen_new_label();
4949
    TCGv t0 = tcg_temp_new();
4950
    TCGv t1 = tcg_temp_new();
4951
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4952
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4953
    tcg_gen_subfi_tl(t1, 32, t1);
4954
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4955
    tcg_gen_or_tl(t1, t0, t1);
4956
    gen_store_spr(SPR_MQ, t1);
4957
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4958
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4959
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4960
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4961
    gen_set_label(l1);
4962
    tcg_temp_free(t0);
4963
    tcg_temp_free(t1);
4964
    if (unlikely(Rc(ctx->opcode) != 0))
4965
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4966
}
4967

    
4968
/* PowerPC 602 specific instructions */
4969

    
4970
/* dsa  */
4971
static void gen_dsa(DisasContext *ctx)
4972
{
4973
    /* XXX: TODO */
4974
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
4975
}
4976

    
4977
/* esa */
4978
static void gen_esa(DisasContext *ctx)
4979
{
4980
    /* XXX: TODO */
4981
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
4982
}
4983

    
4984
/* mfrom */
4985
static void gen_mfrom(DisasContext *ctx)
4986
{
4987
#if defined(CONFIG_USER_ONLY)
4988
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4989
#else
4990
    if (unlikely(!ctx->mem_idx)) {
4991
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4992
        return;
4993
    }
4994
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4995
#endif
4996
}
4997

    
4998
/* 602 - 603 - G2 TLB management */
4999

    
5000
/* tlbld */
5001
static void gen_tlbld_6xx(DisasContext *ctx)
5002
{
5003
#if defined(CONFIG_USER_ONLY)
5004
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5005
#else
5006
    if (unlikely(!ctx->mem_idx)) {
5007
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5008
        return;
5009
    }
5010
    gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5011
#endif
5012
}
5013

    
5014
/* tlbli */
5015
static void gen_tlbli_6xx(DisasContext *ctx)
5016
{
5017
#if defined(CONFIG_USER_ONLY)
5018
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5019
#else
5020
    if (unlikely(!ctx->mem_idx)) {
5021
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5022
        return;
5023
    }
5024
    gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5025
#endif
5026
}
5027

    
5028
/* 74xx TLB management */
5029

    
5030
/* tlbld */
5031
static void gen_tlbld_74xx(DisasContext *ctx)
5032
{
5033
#if defined(CONFIG_USER_ONLY)
5034
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5035
#else
5036
    if (unlikely(!ctx->mem_idx)) {
5037
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5038
        return;
5039
    }
5040
    gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5041
#endif
5042
}
5043

    
5044
/* tlbli */
5045
static void gen_tlbli_74xx(DisasContext *ctx)
5046
{
5047
#if defined(CONFIG_USER_ONLY)
5048
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5049
#else
5050
    if (unlikely(!ctx->mem_idx)) {
5051
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5052
        return;
5053
    }
5054
    gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5055
#endif
5056
}
5057

    
5058
/* POWER instructions not in PowerPC 601 */
5059

    
5060
/* clf */
5061
static void gen_clf(DisasContext *ctx)
5062
{
5063
    /* Cache line flush: implemented as no-op */
5064
}
5065

    
5066
/* cli */
5067
static void gen_cli(DisasContext *ctx)
5068
{
5069
    /* Cache line invalidate: privileged and treated as no-op */
5070
#if defined(CONFIG_USER_ONLY)
5071
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5072
#else
5073
    if (unlikely(!ctx->mem_idx)) {
5074
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5075
        return;
5076
    }
5077
#endif
5078
}
5079

    
5080
/* dclst */
5081
static void gen_dclst(DisasContext *ctx)
5082
{
5083
    /* Data cache line store: treated as no-op */
5084
}
5085

    
5086
static void gen_mfsri(DisasContext *ctx)
5087
{
5088
#if defined(CONFIG_USER_ONLY)
5089
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5090
#else
5091
    int ra = rA(ctx->opcode);
5092
    int rd = rD(ctx->opcode);
5093
    TCGv t0;
5094
    if (unlikely(!ctx->mem_idx)) {
5095
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5096
        return;
5097
    }
5098
    t0 = tcg_temp_new();
5099
    gen_addr_reg_index(ctx, t0);
5100
    tcg_gen_shri_tl(t0, t0, 28);
5101
    tcg_gen_andi_tl(t0, t0, 0xF);
5102
    gen_helper_load_sr(cpu_gpr[rd], t0);
5103
    tcg_temp_free(t0);
5104
    if (ra != 0 && ra != rd)
5105
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5106
#endif
5107
}
5108

    
5109
static void gen_rac(DisasContext *ctx)
5110
{
5111
#if defined(CONFIG_USER_ONLY)
5112
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5113
#else
5114
    TCGv t0;
5115
    if (unlikely(!ctx->mem_idx)) {
5116
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5117
        return;
5118
    }
5119
    t0 = tcg_temp_new();
5120
    gen_addr_reg_index(ctx, t0);
5121
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
5122
    tcg_temp_free(t0);
5123
#endif
5124
}
5125

    
5126
static void gen_rfsvc(DisasContext *ctx)
5127
{
5128
#if defined(CONFIG_USER_ONLY)
5129
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5130
#else
5131
    if (unlikely(!ctx->mem_idx)) {
5132
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5133
        return;
5134
    }
5135
    gen_helper_rfsvc();
5136
    gen_sync_exception(ctx);
5137
#endif
5138
}
5139

    
5140
/* svc is not implemented for now */
5141

    
5142
/* POWER2 specific instructions */
5143
/* Quad manipulation (load/store two floats at a time) */
5144

    
5145
/* lfq */
5146
static void gen_lfq(DisasContext *ctx)
5147
{
5148
    int rd = rD(ctx->opcode);
5149
    TCGv t0;
5150
    gen_set_access_type(ctx, ACCESS_FLOAT);
5151
    t0 = tcg_temp_new();
5152
    gen_addr_imm_index(ctx, t0, 0);
5153
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5154
    gen_addr_add(ctx, t0, t0, 8);
5155
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5156
    tcg_temp_free(t0);
5157
}
5158

    
5159
/* lfqu */
5160
static void gen_lfqu(DisasContext *ctx)
5161
{
5162
    int ra = rA(ctx->opcode);
5163
    int rd = rD(ctx->opcode);
5164
    TCGv t0, t1;
5165
    gen_set_access_type(ctx, ACCESS_FLOAT);
5166
    t0 = tcg_temp_new();
5167
    t1 = tcg_temp_new();
5168
    gen_addr_imm_index(ctx, t0, 0);
5169
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5170
    gen_addr_add(ctx, t1, t0, 8);
5171
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5172
    if (ra != 0)
5173
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5174
    tcg_temp_free(t0);
5175
    tcg_temp_free(t1);
5176
}
5177

    
5178
/* lfqux */
5179
static void gen_lfqux(DisasContext *ctx)
5180
{
5181
    int ra = rA(ctx->opcode);
5182
    int rd = rD(ctx->opcode);
5183
    gen_set_access_type(ctx, ACCESS_FLOAT);
5184
    TCGv t0, t1;
5185
    t0 = tcg_temp_new();
5186
    gen_addr_reg_index(ctx, t0);
5187
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5188
    t1 = tcg_temp_new();
5189
    gen_addr_add(ctx, t1, t0, 8);
5190
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5191
    tcg_temp_free(t1);
5192
    if (ra != 0)
5193
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5194
    tcg_temp_free(t0);
5195
}
5196

    
5197
/* lfqx */
5198
static void gen_lfqx(DisasContext *ctx)
5199
{
5200
    int rd = rD(ctx->opcode);
5201
    TCGv t0;
5202
    gen_set_access_type(ctx, ACCESS_FLOAT);
5203
    t0 = tcg_temp_new();
5204
    gen_addr_reg_index(ctx, t0);
5205
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5206
    gen_addr_add(ctx, t0, t0, 8);
5207
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5208
    tcg_temp_free(t0);
5209
}
5210

    
5211
/* stfq */
5212
static void gen_stfq(DisasContext *ctx)
5213
{
5214
    int rd = rD(ctx->opcode);
5215
    TCGv t0;
5216
    gen_set_access_type(ctx, ACCESS_FLOAT);
5217
    t0 = tcg_temp_new();
5218
    gen_addr_imm_index(ctx, t0, 0);
5219
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5220
    gen_addr_add(ctx, t0, t0, 8);
5221
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5222
    tcg_temp_free(t0);
5223
}
5224

    
5225
/* stfqu */
5226
static void gen_stfqu(DisasContext *ctx)
5227
{
5228
    int ra = rA(ctx->opcode);
5229
    int rd = rD(ctx->opcode);
5230
    TCGv t0, t1;
5231
    gen_set_access_type(ctx, ACCESS_FLOAT);
5232
    t0 = tcg_temp_new();
5233
    gen_addr_imm_index(ctx, t0, 0);
5234
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5235
    t1 = tcg_temp_new();
5236
    gen_addr_add(ctx, t1, t0, 8);
5237
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5238
    tcg_temp_free(t1);
5239
    if (ra != 0)
5240
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5241
    tcg_temp_free(t0);
5242
}
5243

    
5244
/* stfqux */
5245
static void gen_stfqux(DisasContext *ctx)
5246
{
5247
    int ra = rA(ctx->opcode);
5248
    int rd = rD(ctx->opcode);
5249
    TCGv t0, t1;
5250
    gen_set_access_type(ctx, ACCESS_FLOAT);
5251
    t0 = tcg_temp_new();
5252
    gen_addr_reg_index(ctx, t0);
5253
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5254
    t1 = tcg_temp_new();
5255
    gen_addr_add(ctx, t1, t0, 8);
5256
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5257
    tcg_temp_free(t1);
5258
    if (ra != 0)
5259
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5260
    tcg_temp_free(t0);
5261
}
5262

    
5263
/* stfqx */
5264
static void gen_stfqx(DisasContext *ctx)
5265
{
5266
    int rd = rD(ctx->opcode);
5267
    TCGv t0;
5268
    gen_set_access_type(ctx, ACCESS_FLOAT);
5269
    t0 = tcg_temp_new();
5270
    gen_addr_reg_index(ctx, t0);
5271
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5272
    gen_addr_add(ctx, t0, t0, 8);
5273
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5274
    tcg_temp_free(t0);
5275
}
5276

    
5277
/* BookE specific instructions */
5278

    
5279
/* XXX: not implemented on 440 ? */
5280
static void gen_mfapidi(DisasContext *ctx)
5281
{
5282
    /* XXX: TODO */
5283
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5284
}
5285

    
5286
/* XXX: not implemented on 440 ? */
5287
static void gen_tlbiva(DisasContext *ctx)
5288
{
5289
#if defined(CONFIG_USER_ONLY)
5290
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5291
#else
5292
    TCGv t0;
5293
    if (unlikely(!ctx->mem_idx)) {
5294
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5295
        return;
5296
    }
5297
    t0 = tcg_temp_new();
5298
    gen_addr_reg_index(ctx, t0);
5299
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
5300
    tcg_temp_free(t0);
5301
#endif
5302
}
5303

    
5304
/* All 405 MAC instructions are translated here */
5305
static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5306
                                                int opc2, int opc3,
5307
                                                int ra, int rb, int rt, int Rc)
5308
{
5309
    TCGv t0, t1;
5310

    
5311
    t0 = tcg_temp_local_new();
5312
    t1 = tcg_temp_local_new();
5313

    
5314
    switch (opc3 & 0x0D) {
5315
    case 0x05:
5316
        /* macchw    - macchw.    - macchwo   - macchwo.   */
5317
        /* macchws   - macchws.   - macchwso  - macchwso.  */
5318
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
5319
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
5320
        /* mulchw - mulchw. */
5321
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5322
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5323
        tcg_gen_ext16s_tl(t1, t1);
5324
        break;
5325
    case 0x04:
5326
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
5327
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
5328
        /* mulchwu - mulchwu. */
5329
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5330
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5331
        tcg_gen_ext16u_tl(t1, t1);
5332
        break;
5333
    case 0x01:
5334
        /* machhw    - machhw.    - machhwo   - machhwo.   */
5335
        /* machhws   - machhws.   - machhwso  - machhwso.  */
5336
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
5337
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
5338
        /* mulhhw - mulhhw. */
5339
        tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5340
        tcg_gen_ext16s_tl(t0, t0);
5341
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5342
        tcg_gen_ext16s_tl(t1, t1);
5343
        break;
5344
    case 0x00:
5345
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
5346
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
5347
        /* mulhhwu - mulhhwu. */
5348
        tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5349
        tcg_gen_ext16u_tl(t0, t0);
5350
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5351
        tcg_gen_ext16u_tl(t1, t1);
5352
        break;
5353
    case 0x0D:
5354
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
5355
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
5356
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
5357
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
5358
        /* mullhw - mullhw. */
5359
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5360
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5361
        break;
5362
    case 0x0C:
5363
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
5364
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
5365
        /* mullhwu - mullhwu. */
5366
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5367
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5368
        break;
5369
    }
5370
    if (opc2 & 0x04) {
5371
        /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5372
        tcg_gen_mul_tl(t1, t0, t1);
5373
        if (opc2 & 0x02) {
5374
            /* nmultiply-and-accumulate (0x0E) */
5375
            tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5376
        } else {
5377
            /* multiply-and-accumulate (0x0C) */
5378
            tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5379
        }
5380

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

    
5385
            if (opc3 & 0x10) {
5386
                /* Start with XER OV disabled, the most likely case */
5387
                tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5388
            }
5389
            if (opc3 & 0x01) {
5390
                /* Signed */
5391
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5392
                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5393
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5394
                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
5395
                if (opc3 & 0x02) {
5396
                    /* Saturate */
5397
                    tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5398
                    tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5399
                }
5400
            } else {
5401
                /* Unsigned */
5402
                tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5403
                if (opc3 & 0x02) {
5404
                    /* Saturate */
5405
                    tcg_gen_movi_tl(t0, UINT32_MAX);
5406
                }
5407
            }
5408
            if (opc3 & 0x10) {
5409
                /* Check overflow */
5410
                tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5411
            }
5412
            gen_set_label(l1);
5413
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
5414
        }
5415
    } else {
5416
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5417
    }
5418
    tcg_temp_free(t0);
5419
    tcg_temp_free(t1);
5420
    if (unlikely(Rc) != 0) {
5421
        /* Update Rc0 */
5422
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5423
    }
5424
}
5425

    
5426
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
5427
static void glue(gen_, name)(DisasContext *ctx)                               \
5428
{                                                                             \
5429
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
5430
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
5431
}
5432

    
5433
/* macchw    - macchw.    */
5434
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5435
/* macchwo   - macchwo.   */
5436
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5437
/* macchws   - macchws.   */
5438
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5439
/* macchwso  - macchwso.  */
5440
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5441
/* macchwsu  - macchwsu.  */
5442
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5443
/* macchwsuo - macchwsuo. */
5444
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5445
/* macchwu   - macchwu.   */
5446
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5447
/* macchwuo  - macchwuo.  */
5448
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5449
/* machhw    - machhw.    */
5450
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5451
/* machhwo   - machhwo.   */
5452
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5453
/* machhws   - machhws.   */
5454
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5455
/* machhwso  - machhwso.  */
5456
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5457
/* machhwsu  - machhwsu.  */
5458
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5459
/* machhwsuo - machhwsuo. */
5460
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5461
/* machhwu   - machhwu.   */
5462
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5463
/* machhwuo  - machhwuo.  */
5464
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5465
/* maclhw    - maclhw.    */
5466
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5467
/* maclhwo   - maclhwo.   */
5468
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5469
/* maclhws   - maclhws.   */
5470
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5471
/* maclhwso  - maclhwso.  */
5472
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5473
/* maclhwu   - maclhwu.   */
5474
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5475
/* maclhwuo  - maclhwuo.  */
5476
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5477
/* maclhwsu  - maclhwsu.  */
5478
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5479
/* maclhwsuo - maclhwsuo. */
5480
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5481
/* nmacchw   - nmacchw.   */
5482
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5483
/* nmacchwo  - nmacchwo.  */
5484
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5485
/* nmacchws  - nmacchws.  */
5486
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5487
/* nmacchwso - nmacchwso. */
5488
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5489
/* nmachhw   - nmachhw.   */
5490
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5491
/* nmachhwo  - nmachhwo.  */
5492
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5493
/* nmachhws  - nmachhws.  */
5494
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5495
/* nmachhwso - nmachhwso. */
5496
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5497
/* nmaclhw   - nmaclhw.   */
5498
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5499
/* nmaclhwo  - nmaclhwo.  */
5500
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5501
/* nmaclhws  - nmaclhws.  */
5502
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5503
/* nmaclhwso - nmaclhwso. */
5504
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5505

    
5506
/* mulchw  - mulchw.  */
5507
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5508
/* mulchwu - mulchwu. */
5509
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5510
/* mulhhw  - mulhhw.  */
5511
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5512
/* mulhhwu - mulhhwu. */
5513
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5514
/* mullhw  - mullhw.  */
5515
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5516
/* mullhwu - mullhwu. */
5517
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5518

    
5519
/* mfdcr */
5520
static void gen_mfdcr(DisasContext *ctx)
5521
{
5522
#if defined(CONFIG_USER_ONLY)
5523
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5524
#else
5525
    TCGv dcrn;
5526
    if (unlikely(!ctx->mem_idx)) {
5527
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5528
        return;
5529
    }
5530
    /* NIP cannot be restored if the memory exception comes from an helper */
5531
    gen_update_nip(ctx, ctx->nip - 4);
5532
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5533
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
5534
    tcg_temp_free(dcrn);
5535
#endif
5536
}
5537

    
5538
/* mtdcr */
5539
static void gen_mtdcr(DisasContext *ctx)
5540
{
5541
#if defined(CONFIG_USER_ONLY)
5542
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5543
#else
5544
    TCGv dcrn;
5545
    if (unlikely(!ctx->mem_idx)) {
5546
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5547
        return;
5548
    }
5549
    /* NIP cannot be restored if the memory exception comes from an helper */
5550
    gen_update_nip(ctx, ctx->nip - 4);
5551
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5552
    gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
5553
    tcg_temp_free(dcrn);
5554
#endif
5555
}
5556

    
5557
/* mfdcrx */
5558
/* XXX: not implemented on 440 ? */
5559
static void gen_mfdcrx(DisasContext *ctx)
5560
{
5561
#if defined(CONFIG_USER_ONLY)
5562
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5563
#else
5564
    if (unlikely(!ctx->mem_idx)) {
5565
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5566
        return;
5567
    }
5568
    /* NIP cannot be restored if the memory exception comes from an helper */
5569
    gen_update_nip(ctx, ctx->nip - 4);
5570
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5571
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5572
#endif
5573
}
5574

    
5575
/* mtdcrx */
5576
/* XXX: not implemented on 440 ? */
5577
static void gen_mtdcrx(DisasContext *ctx)
5578
{
5579
#if defined(CONFIG_USER_ONLY)
5580
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5581
#else
5582
    if (unlikely(!ctx->mem_idx)) {
5583
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5584
        return;
5585
    }
5586
    /* NIP cannot be restored if the memory exception comes from an helper */
5587
    gen_update_nip(ctx, ctx->nip - 4);
5588
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5589
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5590
#endif
5591
}
5592

    
5593
/* mfdcrux (PPC 460) : user-mode access to DCR */
5594
static void gen_mfdcrux(DisasContext *ctx)
5595
{
5596
    /* NIP cannot be restored if the memory exception comes from an helper */
5597
    gen_update_nip(ctx, ctx->nip - 4);
5598
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5599
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5600
}
5601

    
5602
/* mtdcrux (PPC 460) : user-mode access to DCR */
5603
static void gen_mtdcrux(DisasContext *ctx)
5604
{
5605
    /* NIP cannot be restored if the memory exception comes from an helper */
5606
    gen_update_nip(ctx, ctx->nip - 4);
5607
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5608
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5609
}
5610

    
5611
/* dccci */
5612
static void gen_dccci(DisasContext *ctx)
5613
{
5614
#if defined(CONFIG_USER_ONLY)
5615
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5616
#else
5617
    if (unlikely(!ctx->mem_idx)) {
5618
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5619
        return;
5620
    }
5621
    /* interpreted as no-op */
5622
#endif
5623
}
5624

    
5625
/* dcread */
5626
static void gen_dcread(DisasContext *ctx)
5627
{
5628
#if defined(CONFIG_USER_ONLY)
5629
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5630
#else
5631
    TCGv EA, val;
5632
    if (unlikely(!ctx->mem_idx)) {
5633
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5634
        return;
5635
    }
5636
    gen_set_access_type(ctx, ACCESS_CACHE);
5637
    EA = tcg_temp_new();
5638
    gen_addr_reg_index(ctx, EA);
5639
    val = tcg_temp_new();
5640
    gen_qemu_ld32u(ctx, val, EA);
5641
    tcg_temp_free(val);
5642
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5643
    tcg_temp_free(EA);
5644
#endif
5645
}
5646

    
5647
/* icbt */
5648
static void gen_icbt_40x(DisasContext *ctx)
5649
{
5650
    /* interpreted as no-op */
5651
    /* XXX: specification say this is treated as a load by the MMU
5652
     *      but does not generate any exception
5653
     */
5654
}
5655

    
5656
/* iccci */
5657
static void gen_iccci(DisasContext *ctx)
5658
{
5659
#if defined(CONFIG_USER_ONLY)
5660
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5661
#else
5662
    if (unlikely(!ctx->mem_idx)) {
5663
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5664
        return;
5665
    }
5666
    /* interpreted as no-op */
5667
#endif
5668
}
5669

    
5670
/* icread */
5671
static void gen_icread(DisasContext *ctx)
5672
{
5673
#if defined(CONFIG_USER_ONLY)
5674
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5675
#else
5676
    if (unlikely(!ctx->mem_idx)) {
5677
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5678
        return;
5679
    }
5680
    /* interpreted as no-op */
5681
#endif
5682
}
5683

    
5684
/* rfci (mem_idx only) */
5685
static void gen_rfci_40x(DisasContext *ctx)
5686
{
5687
#if defined(CONFIG_USER_ONLY)
5688
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5689
#else
5690
    if (unlikely(!ctx->mem_idx)) {
5691
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5692
        return;
5693
    }
5694
    /* Restore CPU state */
5695
    gen_helper_40x_rfci();
5696
    gen_sync_exception(ctx);
5697
#endif
5698
}
5699

    
5700
static void gen_rfci(DisasContext *ctx)
5701
{
5702
#if defined(CONFIG_USER_ONLY)
5703
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5704
#else
5705
    if (unlikely(!ctx->mem_idx)) {
5706
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5707
        return;
5708
    }
5709
    /* Restore CPU state */
5710
    gen_helper_rfci();
5711
    gen_sync_exception(ctx);
5712
#endif
5713
}
5714

    
5715
/* BookE specific */
5716

    
5717
/* XXX: not implemented on 440 ? */
5718
static void gen_rfdi(DisasContext *ctx)
5719
{
5720
#if defined(CONFIG_USER_ONLY)
5721
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5722
#else
5723
    if (unlikely(!ctx->mem_idx)) {
5724
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5725
        return;
5726
    }
5727
    /* Restore CPU state */
5728
    gen_helper_rfdi();
5729
    gen_sync_exception(ctx);
5730
#endif
5731
}
5732

    
5733
/* XXX: not implemented on 440 ? */
5734
static void gen_rfmci(DisasContext *ctx)
5735
{
5736
#if defined(CONFIG_USER_ONLY)
5737
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5738
#else
5739
    if (unlikely(!ctx->mem_idx)) {
5740
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5741
        return;
5742
    }
5743
    /* Restore CPU state */
5744
    gen_helper_rfmci();
5745
    gen_sync_exception(ctx);
5746
#endif
5747
}
5748

    
5749
/* TLB management - PowerPC 405 implementation */
5750

    
5751
/* tlbre */
5752
static void gen_tlbre_40x(DisasContext *ctx)
5753
{
5754
#if defined(CONFIG_USER_ONLY)
5755
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5756
#else
5757
    if (unlikely(!ctx->mem_idx)) {
5758
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5759
        return;
5760
    }
5761
    switch (rB(ctx->opcode)) {
5762
    case 0:
5763
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5764
        break;
5765
    case 1:
5766
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5767
        break;
5768
    default:
5769
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5770
        break;
5771
    }
5772
#endif
5773
}
5774

    
5775
/* tlbsx - tlbsx. */
5776
static void gen_tlbsx_40x(DisasContext *ctx)
5777
{
5778
#if defined(CONFIG_USER_ONLY)
5779
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5780
#else
5781
    TCGv t0;
5782
    if (unlikely(!ctx->mem_idx)) {
5783
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5784
        return;
5785
    }
5786
    t0 = tcg_temp_new();
5787
    gen_addr_reg_index(ctx, t0);
5788
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5789
    tcg_temp_free(t0);
5790
    if (Rc(ctx->opcode)) {
5791
        int l1 = gen_new_label();
5792
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5793
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5794
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5795
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5796
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5797
        gen_set_label(l1);
5798
    }
5799
#endif
5800
}
5801

    
5802
/* tlbwe */
5803
static void gen_tlbwe_40x(DisasContext *ctx)
5804
{
5805
#if defined(CONFIG_USER_ONLY)
5806
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5807
#else
5808
    if (unlikely(!ctx->mem_idx)) {
5809
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5810
        return;
5811
    }
5812
    switch (rB(ctx->opcode)) {
5813
    case 0:
5814
        gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5815
        break;
5816
    case 1:
5817
        gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5818
        break;
5819
    default:
5820
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5821
        break;
5822
    }
5823
#endif
5824
}
5825

    
5826
/* TLB management - PowerPC 440 implementation */
5827

    
5828
/* tlbre */
5829
static void gen_tlbre_440(DisasContext *ctx)
5830
{
5831
#if defined(CONFIG_USER_ONLY)
5832
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5833
#else
5834
    if (unlikely(!ctx->mem_idx)) {
5835
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5836
        return;
5837
    }
5838
    switch (rB(ctx->opcode)) {
5839
    case 0:
5840
    case 1:
5841
    case 2:
5842
        {
5843
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5844
            gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5845
            tcg_temp_free_i32(t0);
5846
        }
5847
        break;
5848
    default:
5849
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5850
        break;
5851
    }
5852
#endif
5853
}
5854

    
5855
/* tlbsx - tlbsx. */
5856
static void gen_tlbsx_440(DisasContext *ctx)
5857
{
5858
#if defined(CONFIG_USER_ONLY)
5859
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5860
#else
5861
    TCGv t0;
5862
    if (unlikely(!ctx->mem_idx)) {
5863
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5864
        return;
5865
    }
5866
    t0 = tcg_temp_new();
5867
    gen_addr_reg_index(ctx, t0);
5868
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5869
    tcg_temp_free(t0);
5870
    if (Rc(ctx->opcode)) {
5871
        int l1 = gen_new_label();
5872
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5873
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5874
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5875
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5876
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5877
        gen_set_label(l1);
5878
    }
5879
#endif
5880
}
5881

    
5882
/* tlbwe */
5883
static void gen_tlbwe_440(DisasContext *ctx)
5884
{
5885
#if defined(CONFIG_USER_ONLY)
5886
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5887
#else
5888
    if (unlikely(!ctx->mem_idx)) {
5889
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5890
        return;
5891
    }
5892
    switch (rB(ctx->opcode)) {
5893
    case 0:
5894
    case 1:
5895
    case 2:
5896
        {
5897
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5898
            gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5899
            tcg_temp_free_i32(t0);
5900
        }
5901
        break;
5902
    default:
5903
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5904
        break;
5905
    }
5906
#endif
5907
}
5908

    
5909
/* wrtee */
5910
static void gen_wrtee(DisasContext *ctx)
5911
{
5912
#if defined(CONFIG_USER_ONLY)
5913
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5914
#else
5915
    TCGv t0;
5916
    if (unlikely(!ctx->mem_idx)) {
5917
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5918
        return;
5919
    }
5920
    t0 = tcg_temp_new();
5921
    tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
5922
    tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
5923
    tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
5924
    tcg_temp_free(t0);
5925
    /* Stop translation to have a chance to raise an exception
5926
     * if we just set msr_ee to 1
5927
     */
5928
    gen_stop_exception(ctx);
5929
#endif
5930
}
5931

    
5932
/* wrteei */
5933
static void gen_wrteei(DisasContext *ctx)
5934
{
5935
#if defined(CONFIG_USER_ONLY)
5936
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5937
#else
5938
    if (unlikely(!ctx->mem_idx)) {
5939
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5940
        return;
5941
    }
5942
    if (ctx->opcode & 0x00008000) {
5943
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
5944
        /* Stop translation to have a chance to raise an exception */
5945
        gen_stop_exception(ctx);
5946
    } else {
5947
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
5948
    }
5949
#endif
5950
}
5951

    
5952
/* PowerPC 440 specific instructions */
5953

    
5954
/* dlmzb */
5955
static void gen_dlmzb(DisasContext *ctx)
5956
{
5957
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
5958
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
5959
                     cpu_gpr[rB(ctx->opcode)], t0);
5960
    tcg_temp_free_i32(t0);
5961
}
5962

    
5963
/* mbar replaces eieio on 440 */
5964
static void gen_mbar(DisasContext *ctx)
5965
{
5966
    /* interpreted as no-op */
5967
}
5968

    
5969
/* msync replaces sync on 440 */
5970
static void gen_msync(DisasContext *ctx)
5971
{
5972
    /* interpreted as no-op */
5973
}
5974

    
5975
/* icbt */
5976
static void gen_icbt_440(DisasContext *ctx)
5977
{
5978
    /* interpreted as no-op */
5979
    /* XXX: specification say this is treated as a load by the MMU
5980
     *      but does not generate any exception
5981
     */
5982
}
5983

    
5984
/***                      Altivec vector extension                         ***/
5985
/* Altivec registers moves */
5986

    
5987
static always_inline TCGv_ptr gen_avr_ptr(int reg)
5988
{
5989
    TCGv_ptr r = tcg_temp_new_ptr();
5990
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
5991
    return r;
5992
}
5993

    
5994
#define GEN_VR_LDX(name, opc2, opc3)                                          \
5995
static void glue(gen_, name)(DisasContext *ctx)                                       \
5996
{                                                                             \
5997
    TCGv EA;                                                                  \
5998
    if (unlikely(!ctx->altivec_enabled)) {                                    \
5999
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6000
        return;                                                               \
6001
    }                                                                         \
6002
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6003
    EA = tcg_temp_new();                                                      \
6004
    gen_addr_reg_index(ctx, EA);                                              \
6005
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6006
    if (ctx->le_mode) {                                                       \
6007
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6008
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6009
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6010
    } else {                                                                  \
6011
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6012
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6013
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6014
    }                                                                         \
6015
    tcg_temp_free(EA);                                                        \
6016
}
6017

    
6018
#define GEN_VR_STX(name, opc2, opc3)                                          \
6019
static void gen_st##name(DisasContext *ctx)                                   \
6020
{                                                                             \
6021
    TCGv EA;                                                                  \
6022
    if (unlikely(!ctx->altivec_enabled)) {                                    \
6023
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6024
        return;                                                               \
6025
    }                                                                         \
6026
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6027
    EA = tcg_temp_new();                                                      \
6028
    gen_addr_reg_index(ctx, EA);                                              \
6029
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6030
    if (ctx->le_mode) {                                                       \
6031
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6032
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6033
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6034
    } else {                                                                  \
6035
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6036
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6037
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6038
    }                                                                         \
6039
    tcg_temp_free(EA);                                                        \
6040
}
6041

    
6042
#define GEN_VR_LVE(name, opc2, opc3)                                    \
6043
static void gen_lve##name(DisasContext *ctx)                            \
6044
    {                                                                   \
6045
        TCGv EA;                                                        \
6046
        TCGv_ptr rs;                                                    \
6047
        if (unlikely(!ctx->altivec_enabled)) {                          \
6048
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6049
            return;                                                     \
6050
        }                                                               \
6051
        gen_set_access_type(ctx, ACCESS_INT);                           \
6052
        EA = tcg_temp_new();                                            \
6053
        gen_addr_reg_index(ctx, EA);                                    \
6054
        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6055
        gen_helper_lve##name (rs, EA);                                  \
6056
        tcg_temp_free(EA);                                              \
6057
        tcg_temp_free_ptr(rs);                                          \
6058
    }
6059

    
6060
#define GEN_VR_STVE(name, opc2, opc3)                                   \
6061
static void gen_stve##name(DisasContext *ctx)                           \
6062
    {                                                                   \
6063
        TCGv EA;                                                        \
6064
        TCGv_ptr rs;                                                    \
6065
        if (unlikely(!ctx->altivec_enabled)) {                          \
6066
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6067
            return;                                                     \
6068
        }                                                               \
6069
        gen_set_access_type(ctx, ACCESS_INT);                           \
6070
        EA = tcg_temp_new();                                            \
6071
        gen_addr_reg_index(ctx, EA);                                    \
6072
        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6073
        gen_helper_stve##name (rs, EA);                                 \
6074
        tcg_temp_free(EA);                                              \
6075
        tcg_temp_free_ptr(rs);                                          \
6076
    }
6077

    
6078
GEN_VR_LDX(lvx, 0x07, 0x03);
6079
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6080
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6081

    
6082
GEN_VR_LVE(bx, 0x07, 0x00);
6083
GEN_VR_LVE(hx, 0x07, 0x01);
6084
GEN_VR_LVE(wx, 0x07, 0x02);
6085

    
6086
GEN_VR_STX(svx, 0x07, 0x07);
6087
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6088
GEN_VR_STX(svxl, 0x07, 0x0F);
6089

    
6090
GEN_VR_STVE(bx, 0x07, 0x04);
6091
GEN_VR_STVE(hx, 0x07, 0x05);
6092
GEN_VR_STVE(wx, 0x07, 0x06);
6093

    
6094
static void gen_lvsl(DisasContext *ctx)
6095
{
6096
    TCGv_ptr rd;
6097
    TCGv EA;
6098
    if (unlikely(!ctx->altivec_enabled)) {
6099
        gen_exception(ctx, POWERPC_EXCP_VPU);
6100
        return;
6101
    }
6102
    EA = tcg_temp_new();
6103
    gen_addr_reg_index(ctx, EA);
6104
    rd = gen_avr_ptr(rD(ctx->opcode));
6105
    gen_helper_lvsl(rd, EA);
6106
    tcg_temp_free(EA);
6107
    tcg_temp_free_ptr(rd);
6108
}
6109

    
6110
static void gen_lvsr(DisasContext *ctx)
6111
{
6112
    TCGv_ptr rd;
6113
    TCGv EA;
6114
    if (unlikely(!ctx->altivec_enabled)) {
6115
        gen_exception(ctx, POWERPC_EXCP_VPU);
6116
        return;
6117
    }
6118
    EA = tcg_temp_new();
6119
    gen_addr_reg_index(ctx, EA);
6120
    rd = gen_avr_ptr(rD(ctx->opcode));
6121
    gen_helper_lvsr(rd, EA);
6122
    tcg_temp_free(EA);
6123
    tcg_temp_free_ptr(rd);
6124
}
6125

    
6126
static void gen_mfvscr(DisasContext *ctx)
6127
{
6128
    TCGv_i32 t;
6129
    if (unlikely(!ctx->altivec_enabled)) {
6130
        gen_exception(ctx, POWERPC_EXCP_VPU);
6131
        return;
6132
    }
6133
    tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
6134
    t = tcg_temp_new_i32();
6135
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, vscr));
6136
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6137
    tcg_temp_free_i32(t);
6138
}
6139

    
6140
static void gen_mtvscr(DisasContext *ctx)
6141
{
6142
    TCGv_ptr p;
6143
    if (unlikely(!ctx->altivec_enabled)) {
6144
        gen_exception(ctx, POWERPC_EXCP_VPU);
6145
        return;
6146
    }
6147
    p = gen_avr_ptr(rD(ctx->opcode));
6148
    gen_helper_mtvscr(p);
6149
    tcg_temp_free_ptr(p);
6150
}
6151

    
6152
/* Logical operations */
6153
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
6154
static void glue(gen_, name)(DisasContext *ctx)                                 \
6155
{                                                                       \
6156
    if (unlikely(!ctx->altivec_enabled)) {                              \
6157
        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
6158
        return;                                                         \
6159
    }                                                                   \
6160
    tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
6161
    tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
6162
}
6163

    
6164
GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
6165
GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
6166
GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
6167
GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
6168
GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
6169

    
6170
#define GEN_VXFORM(name, opc2, opc3)                                    \
6171
static void glue(gen_, name)(DisasContext *ctx)                                 \
6172
{                                                                       \
6173
    TCGv_ptr ra, rb, rd;                                                \
6174
    if (unlikely(!ctx->altivec_enabled)) {                              \
6175
        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
6176
        return;                                                         \
6177
    }                                                                   \
6178
    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
6179
    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
6180
    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
6181
    gen_helper_##name (rd, ra, rb);                                     \
6182
    tcg_temp_free_ptr(ra);                                              \
6183
    tcg_temp_free_ptr(rb);                                              \
6184
    tcg_temp_free_ptr(rd);                                              \
6185
}
6186

    
6187
GEN_VXFORM(vaddubm, 0, 0);
6188
GEN_VXFORM(vadduhm, 0, 1);
6189
GEN_VXFORM(vadduwm, 0, 2);
6190
GEN_VXFORM(vsububm, 0, 16);
6191
GEN_VXFORM(vsubuhm, 0, 17);
6192
GEN_VXFORM(vsubuwm, 0, 18);
6193
GEN_VXFORM(vmaxub, 1, 0);
6194
GEN_VXFORM(vmaxuh, 1, 1);
6195
GEN_VXFORM(vmaxuw, 1, 2);
6196
GEN_VXFORM(vmaxsb, 1, 4);
6197
GEN_VXFORM(vmaxsh, 1, 5);
6198
GEN_VXFORM(vmaxsw, 1, 6);
6199
GEN_VXFORM(vminub, 1, 8);
6200
GEN_VXFORM(vminuh, 1, 9);
6201
GEN_VXFORM(vminuw, 1, 10);
6202
GEN_VXFORM(vminsb, 1, 12);
6203
GEN_VXFORM(vminsh, 1, 13);
6204
GEN_VXFORM(vminsw, 1, 14);
6205
GEN_VXFORM(vavgub, 1, 16);
6206
GEN_VXFORM(vavguh, 1, 17);
6207
GEN_VXFORM(vavguw, 1, 18);
6208
GEN_VXFORM(vavgsb, 1, 20);
6209
GEN_VXFORM(vavgsh, 1, 21);
6210
GEN_VXFORM(vavgsw, 1, 22);
6211
GEN_VXFORM(vmrghb, 6, 0);
6212
GEN_VXFORM(vmrghh, 6, 1);
6213
GEN_VXFORM(vmrghw, 6, 2);
6214
GEN_VXFORM(vmrglb, 6, 4);
6215
GEN_VXFORM(vmrglh, 6, 5);
6216
GEN_VXFORM(vmrglw, 6, 6);
6217
GEN_VXFORM(vmuloub, 4, 0);
6218
GEN_VXFORM(vmulouh, 4, 1);
6219
GEN_VXFORM(vmulosb, 4, 4);
6220
GEN_VXFORM(vmulosh, 4, 5);
6221
GEN_VXFORM(vmuleub, 4, 8);
6222
GEN_VXFORM(vmuleuh, 4, 9);
6223
GEN_VXFORM(vmulesb, 4, 12);
6224
GEN_VXFORM(vmulesh, 4, 13);
6225
GEN_VXFORM(vslb, 2, 4);
6226
GEN_VXFORM(vslh, 2, 5);
6227
GEN_VXFORM(vslw, 2, 6);
6228
GEN_VXFORM(vsrb, 2, 8);
6229
GEN_VXFORM(vsrh, 2, 9);
6230
GEN_VXFORM(vsrw, 2, 10);
6231
GEN_VXFORM(vsrab, 2, 12);
6232
GEN_VXFORM(vsrah, 2, 13);
6233
GEN_VXFORM(vsraw, 2, 14);
6234
GEN_VXFORM(vslo, 6, 16);
6235
GEN_VXFORM(vsro, 6, 17);
6236
GEN_VXFORM(vaddcuw, 0, 6);
6237
GEN_VXFORM(vsubcuw, 0, 22);
6238
GEN_VXFORM(vaddubs, 0, 8);
6239
GEN_VXFORM(vadduhs, 0, 9);
6240
GEN_VXFORM(vadduws, 0, 10);
6241
GEN_VXFORM(vaddsbs, 0, 12);
6242
GEN_VXFORM(vaddshs, 0, 13);
6243
GEN_VXFORM(vaddsws, 0, 14);
6244
GEN_VXFORM(vsububs, 0, 24);
6245
GEN_VXFORM(vsubuhs, 0, 25);
6246
GEN_VXFORM(vsubuws, 0, 26);
6247
GEN_VXFORM(vsubsbs, 0, 28);
6248
GEN_VXFORM(vsubshs, 0, 29);
6249
GEN_VXFORM(vsubsws, 0, 30);
6250
GEN_VXFORM(vrlb, 2, 0);
6251
GEN_VXFORM(vrlh, 2, 1);
6252
GEN_VXFORM(vrlw, 2, 2);
6253
GEN_VXFORM(vsl, 2, 7);
6254
GEN_VXFORM(vsr, 2, 11);
6255
GEN_VXFORM(vpkuhum, 7, 0);
6256
GEN_VXFORM(vpkuwum, 7, 1);
6257
GEN_VXFORM(vpkuhus, 7, 2);
6258
GEN_VXFORM(vpkuwus, 7, 3);
6259
GEN_VXFORM(vpkshus, 7, 4);
6260
GEN_VXFORM(vpkswus, 7, 5);
6261
GEN_VXFORM(vpkshss, 7, 6);
6262
GEN_VXFORM(vpkswss, 7, 7);
6263
GEN_VXFORM(vpkpx, 7, 12);
6264
GEN_VXFORM(vsum4ubs, 4, 24);
6265
GEN_VXFORM(vsum4sbs, 4, 28);
6266
GEN_VXFORM(vsum4shs, 4, 25);
6267
GEN_VXFORM(vsum2sws, 4, 26);
6268
GEN_VXFORM(vsumsws, 4, 30);
6269
GEN_VXFORM(vaddfp, 5, 0);
6270
GEN_VXFORM(vsubfp, 5, 1);
6271
GEN_VXFORM(vmaxfp, 5, 16);
6272
GEN_VXFORM(vminfp, 5, 17);
6273

    
6274
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
6275
static void glue(gen_, name)(DisasContext *ctx)                         \
6276
    {                                                                   \
6277
        TCGv_ptr ra, rb, rd;                                            \
6278
        if (unlikely(!ctx->altivec_enabled)) {                          \
6279
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6280
            return;                                                     \
6281
        }                                                               \
6282
        ra = gen_avr_ptr(rA(ctx->opcode));                              \
6283
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
6284
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6285
        gen_helper_##opname (rd, ra, rb);                               \
6286
        tcg_temp_free_ptr(ra);                                          \
6287
        tcg_temp_free_ptr(rb);                                          \
6288
        tcg_temp_free_ptr(rd);                                          \
6289
    }
6290

    
6291
#define GEN_VXRFORM(name, opc2, opc3)                                \
6292
    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
6293
    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
6294

    
6295
GEN_VXRFORM(vcmpequb, 3, 0)
6296
GEN_VXRFORM(vcmpequh, 3, 1)
6297
GEN_VXRFORM(vcmpequw, 3, 2)
6298
GEN_VXRFORM(vcmpgtsb, 3, 12)
6299
GEN_VXRFORM(vcmpgtsh, 3, 13)
6300
GEN_VXRFORM(vcmpgtsw, 3, 14)
6301
GEN_VXRFORM(vcmpgtub, 3, 8)
6302
GEN_VXRFORM(vcmpgtuh, 3, 9)
6303
GEN_VXRFORM(vcmpgtuw, 3, 10)
6304
GEN_VXRFORM(vcmpeqfp, 3, 3)
6305
GEN_VXRFORM(vcmpgefp, 3, 7)
6306
GEN_VXRFORM(vcmpgtfp, 3, 11)
6307
GEN_VXRFORM(vcmpbfp, 3, 15)
6308

    
6309
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
6310
static void glue(gen_, name)(DisasContext *ctx)                         \
6311
    {                                                                   \
6312
        TCGv_ptr rd;                                                    \
6313
        TCGv_i32 simm;                                                  \
6314
        if (unlikely(!ctx->altivec_enabled)) {                          \
6315
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6316
            return;                                                     \
6317
        }                                                               \
6318
        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
6319
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6320
        gen_helper_##name (rd, simm);                                   \
6321
        tcg_temp_free_i32(simm);                                        \
6322
        tcg_temp_free_ptr(rd);                                          \
6323
    }
6324

    
6325
GEN_VXFORM_SIMM(vspltisb, 6, 12);
6326
GEN_VXFORM_SIMM(vspltish, 6, 13);
6327
GEN_VXFORM_SIMM(vspltisw, 6, 14);
6328

    
6329
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
6330
static void glue(gen_, name)(DisasContext *ctx)                                 \
6331
    {                                                                   \
6332
        TCGv_ptr rb, rd;                                                \
6333
        if (unlikely(!ctx->altivec_enabled)) {                          \
6334
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6335
            return;                                                     \
6336
        }                                                               \
6337
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
6338
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6339
        gen_helper_##name (rd, rb);                                     \
6340
        tcg_temp_free_ptr(rb);                                          \
6341
        tcg_temp_free_ptr(rd);                                         \
6342
    }
6343

    
6344
GEN_VXFORM_NOA(vupkhsb, 7, 8);
6345
GEN_VXFORM_NOA(vupkhsh, 7, 9);
6346
GEN_VXFORM_NOA(vupklsb, 7, 10);
6347
GEN_VXFORM_NOA(vupklsh, 7, 11);
6348
GEN_VXFORM_NOA(vupkhpx, 7, 13);
6349
GEN_VXFORM_NOA(vupklpx, 7, 15);
6350
GEN_VXFORM_NOA(vrefp, 5, 4);
6351
GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
6352
GEN_VXFORM_NOA(vlogefp, 5, 7);
6353
GEN_VXFORM_NOA(vrfim, 5, 8);
6354
GEN_VXFORM_NOA(vrfin, 5, 9);
6355
GEN_VXFORM_NOA(vrfip, 5, 10);
6356
GEN_VXFORM_NOA(vrfiz, 5, 11);
6357

    
6358
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
6359
static void glue(gen_, name)(DisasContext *ctx)                                 \
6360
    {                                                                   \
6361
        TCGv_ptr rd;                                                    \
6362
        TCGv_i32 simm;                                                  \
6363
        if (unlikely(!ctx->altivec_enabled)) {                          \
6364
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6365
            return;                                                     \
6366
        }                                                               \
6367
        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
6368
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6369
        gen_helper_##name (rd, simm);                                   \
6370
        tcg_temp_free_i32(simm);                                        \
6371
        tcg_temp_free_ptr(rd);                                          \
6372
    }
6373

    
6374
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
6375
static void glue(gen_, name)(DisasContext *ctx)                                 \
6376
    {                                                                   \
6377
        TCGv_ptr rb, rd;                                                \
6378
        TCGv_i32 uimm;                                                  \
6379
        if (unlikely(!ctx->altivec_enabled)) {                          \
6380
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6381
            return;                                                     \
6382
        }                                                               \
6383
        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
6384
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
6385
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6386
        gen_helper_##name (rd, rb, uimm);                               \
6387
        tcg_temp_free_i32(uimm);                                        \
6388
        tcg_temp_free_ptr(rb);                                          \
6389
        tcg_temp_free_ptr(rd);                                          \
6390
    }
6391

    
6392
GEN_VXFORM_UIMM(vspltb, 6, 8);
6393
GEN_VXFORM_UIMM(vsplth, 6, 9);
6394
GEN_VXFORM_UIMM(vspltw, 6, 10);
6395
GEN_VXFORM_UIMM(vcfux, 5, 12);
6396
GEN_VXFORM_UIMM(vcfsx, 5, 13);
6397
GEN_VXFORM_UIMM(vctuxs, 5, 14);
6398
GEN_VXFORM_UIMM(vctsxs, 5, 15);
6399

    
6400
static void gen_vsldoi(DisasContext *ctx)
6401
{
6402
    TCGv_ptr ra, rb, rd;
6403
    TCGv_i32 sh;
6404
    if (unlikely(!ctx->altivec_enabled)) {
6405
        gen_exception(ctx, POWERPC_EXCP_VPU);
6406
        return;
6407
    }
6408
    ra = gen_avr_ptr(rA(ctx->opcode));
6409
    rb = gen_avr_ptr(rB(ctx->opcode));
6410
    rd = gen_avr_ptr(rD(ctx->opcode));
6411
    sh = tcg_const_i32(VSH(ctx->opcode));
6412
    gen_helper_vsldoi (rd, ra, rb, sh);
6413
    tcg_temp_free_ptr(ra);
6414
    tcg_temp_free_ptr(rb);
6415
    tcg_temp_free_ptr(rd);
6416
    tcg_temp_free_i32(sh);
6417
}
6418

    
6419
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
6420
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                      \
6421
    {                                                                   \
6422
        TCGv_ptr ra, rb, rc, rd;                                        \
6423
        if (unlikely(!ctx->altivec_enabled)) {                          \
6424
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6425
            return;                                                     \
6426
        }                                                               \
6427
        ra = gen_avr_ptr(rA(ctx->opcode));                              \
6428
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
6429
        rc = gen_avr_ptr(rC(ctx->opcode));                              \
6430
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6431
        if (Rc(ctx->opcode)) {                                          \
6432
            gen_helper_##name1 (rd, ra, rb, rc);                        \
6433
        } else {                                                        \
6434
            gen_helper_##name0 (rd, ra, rb, rc);                        \
6435
        }                                                               \
6436
        tcg_temp_free_ptr(ra);                                          \
6437
        tcg_temp_free_ptr(rb);                                          \
6438
        tcg_temp_free_ptr(rc);                                          \
6439
        tcg_temp_free_ptr(rd);                                          \
6440
    }
6441

    
6442
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
6443

    
6444
static void gen_vmladduhm(DisasContext *ctx)
6445
{
6446
    TCGv_ptr ra, rb, rc, rd;
6447
    if (unlikely(!ctx->altivec_enabled)) {
6448
        gen_exception(ctx, POWERPC_EXCP_VPU);
6449
        return;
6450
    }
6451
    ra = gen_avr_ptr(rA(ctx->opcode));
6452
    rb = gen_avr_ptr(rB(ctx->opcode));
6453
    rc = gen_avr_ptr(rC(ctx->opcode));
6454
    rd = gen_avr_ptr(rD(ctx->opcode));
6455
    gen_helper_vmladduhm(rd, ra, rb, rc);
6456
    tcg_temp_free_ptr(ra);
6457
    tcg_temp_free_ptr(rb);
6458
    tcg_temp_free_ptr(rc);
6459
    tcg_temp_free_ptr(rd);
6460
}
6461

    
6462
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
6463
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
6464
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
6465
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6466
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
6467

    
6468
/***                           SPE extension                               ***/
6469
/* Register moves */
6470

    
6471
static always_inline void gen_load_gpr64(TCGv_i64 t, int reg) {
6472
#if defined(TARGET_PPC64)
6473
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
6474
#else
6475
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6476
#endif
6477
}
6478

    
6479
static always_inline void gen_store_gpr64(int reg, TCGv_i64 t) {
6480
#if defined(TARGET_PPC64)
6481
    tcg_gen_mov_i64(cpu_gpr[reg], t);
6482
#else
6483
    TCGv_i64 tmp = tcg_temp_new_i64();
6484
    tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
6485
    tcg_gen_shri_i64(tmp, t, 32);
6486
    tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
6487
    tcg_temp_free_i64(tmp);
6488
#endif
6489
}
6490

    
6491
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
6492
static void glue(gen_, name0##_##name1)(DisasContext *ctx)                    \
6493
{                                                                             \
6494
    if (Rc(ctx->opcode))                                                      \
6495
        gen_##name1(ctx);                                                     \
6496
    else                                                                      \
6497
        gen_##name0(ctx);                                                     \
6498
}
6499

    
6500
/* Handler for undefined SPE opcodes */
6501
static always_inline void gen_speundef (DisasContext *ctx)
6502
{
6503
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6504
}
6505

    
6506
/* SPE logic */
6507
#if defined(TARGET_PPC64)
6508
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
6509
static always_inline void gen_##name (DisasContext *ctx)                      \
6510
{                                                                             \
6511
    if (unlikely(!ctx->spe_enabled)) {                                        \
6512
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6513
        return;                                                               \
6514
    }                                                                         \
6515
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
6516
           cpu_gpr[rB(ctx->opcode)]);                                         \
6517
}
6518
#else
6519
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
6520
static always_inline void gen_##name (DisasContext *ctx)                      \
6521
{                                                                             \
6522
    if (unlikely(!ctx->spe_enabled)) {                                        \
6523
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6524
        return;                                                               \
6525
    }                                                                         \
6526
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
6527
           cpu_gpr[rB(ctx->opcode)]);                                         \
6528
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
6529
           cpu_gprh[rB(ctx->opcode)]);                                        \
6530
}
6531
#endif
6532

    
6533
GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6534
GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6535
GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6536
GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6537
GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6538
GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6539
GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6540
GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
6541

    
6542
/* SPE logic immediate */
6543
#if defined(TARGET_PPC64)
6544
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
6545
static always_inline void gen_##name (DisasContext *ctx)                      \
6546
{                                                                             \
6547
    if (unlikely(!ctx->spe_enabled)) {                                        \
6548
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6549
        return;                                                               \
6550
    }                                                                         \
6551
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6552
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6553
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6554
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6555
    tcg_opi(t0, t0, rB(ctx->opcode));                                         \
6556
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
6557
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6558
    tcg_temp_free_i64(t2);                                                    \
6559
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
6560
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6561
    tcg_temp_free_i32(t0);                                                    \
6562
    tcg_temp_free_i32(t1);                                                    \
6563
}
6564
#else
6565
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
6566
static always_inline void gen_##name (DisasContext *ctx)                      \
6567
{                                                                             \
6568
    if (unlikely(!ctx->spe_enabled)) {                                        \
6569
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6570
        return;                                                               \
6571
    }                                                                         \
6572
    tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],               \
6573
            rB(ctx->opcode));                                                 \
6574
    tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],             \
6575
            rB(ctx->opcode));                                                 \
6576
}
6577
#endif
6578
GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
6579
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
6580
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
6581
GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
6582

    
6583
/* SPE arithmetic */
6584
#if defined(TARGET_PPC64)
6585
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6586
static always_inline void gen_##name (DisasContext *ctx)                      \
6587
{                                                                             \
6588
    if (unlikely(!ctx->spe_enabled)) {                                        \
6589
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6590
        return;                                                               \
6591
    }                                                                         \
6592
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6593
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6594
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6595
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6596
    tcg_op(t0, t0);                                                           \
6597
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
6598
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6599
    tcg_temp_free_i64(t2);                                                    \
6600
    tcg_op(t1, t1);                                                           \
6601
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6602
    tcg_temp_free_i32(t0);                                                    \
6603
    tcg_temp_free_i32(t1);                                                    \
6604
}
6605
#else
6606
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6607
static always_inline void gen_##name (DisasContext *ctx)                      \
6608
{                                                                             \
6609
    if (unlikely(!ctx->spe_enabled)) {                                        \
6610
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6611
        return;                                                               \
6612
    }                                                                         \
6613
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);               \
6614
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);             \
6615
}
6616
#endif
6617

    
6618
static always_inline void gen_op_evabs (TCGv_i32 ret, TCGv_i32 arg1)
6619
{
6620
    int l1 = gen_new_label();
6621
    int l2 = gen_new_label();
6622

    
6623
    tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6624
    tcg_gen_neg_i32(ret, arg1);
6625
    tcg_gen_br(l2);
6626
    gen_set_label(l1);
6627
    tcg_gen_mov_i32(ret, arg1);
6628
    gen_set_label(l2);
6629
}
6630
GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6631
GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6632
GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6633
GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
6634
static always_inline void gen_op_evrndw (TCGv_i32 ret, TCGv_i32 arg1)
6635
{
6636
    tcg_gen_addi_i32(ret, arg1, 0x8000);
6637
    tcg_gen_ext16u_i32(ret, ret);
6638
}
6639
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
6640
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6641
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6642

    
6643
#if defined(TARGET_PPC64)
6644
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
6645
static always_inline void gen_##name (DisasContext *ctx)                      \
6646
{                                                                             \
6647
    if (unlikely(!ctx->spe_enabled)) {                                        \
6648
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6649
        return;                                                               \
6650
    }                                                                         \
6651
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6652
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6653
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
6654
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
6655
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6656
    tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]);                      \
6657
    tcg_op(t0, t0, t2);                                                       \
6658
    tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32);                       \
6659
    tcg_gen_trunc_i64_i32(t1, t3);                                            \
6660
    tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32);                       \
6661
    tcg_gen_trunc_i64_i32(t2, t3);                                            \
6662
    tcg_temp_free_i64(t3);                                                    \
6663
    tcg_op(t1, t1, t2);                                                       \
6664
    tcg_temp_free_i32(t2);                                                    \
6665
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6666
    tcg_temp_free_i32(t0);                                                    \
6667
    tcg_temp_free_i32(t1);                                                    \
6668
}
6669
#else
6670
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
6671
static always_inline void gen_##name (DisasContext *ctx)                      \
6672
{                                                                             \
6673
    if (unlikely(!ctx->spe_enabled)) {                                        \
6674
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6675
        return;                                                               \
6676
    }                                                                         \
6677
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
6678
           cpu_gpr[rB(ctx->opcode)]);                                         \
6679
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
6680
           cpu_gprh[rB(ctx->opcode)]);                                        \
6681
}
6682
#endif
6683

    
6684
static always_inline void gen_op_evsrwu (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6685
{
6686
    TCGv_i32 t0;
6687
    int l1, l2;
6688

    
6689
    l1 = gen_new_label();
6690
    l2 = gen_new_label();
6691
    t0 = tcg_temp_local_new_i32();
6692
    /* No error here: 6 bits are used */
6693
    tcg_gen_andi_i32(t0, arg2, 0x3F);
6694
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6695
    tcg_gen_shr_i32(ret, arg1, t0);
6696
    tcg_gen_br(l2);
6697
    gen_set_label(l1);
6698
    tcg_gen_movi_i32(ret, 0);
6699
    tcg_gen_br(l2);
6700
    tcg_temp_free_i32(t0);
6701
}
6702
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
6703
static always_inline void gen_op_evsrws (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6704
{
6705
    TCGv_i32 t0;
6706
    int l1, l2;
6707

    
6708
    l1 = gen_new_label();
6709
    l2 = gen_new_label();
6710
    t0 = tcg_temp_local_new_i32();
6711
    /* No error here: 6 bits are used */
6712
    tcg_gen_andi_i32(t0, arg2, 0x3F);
6713
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6714
    tcg_gen_sar_i32(ret, arg1, t0);
6715
    tcg_gen_br(l2);
6716
    gen_set_label(l1);
6717
    tcg_gen_movi_i32(ret, 0);
6718
    tcg_gen_br(l2);
6719
    tcg_temp_free_i32(t0);
6720
}
6721
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
6722
static always_inline void gen_op_evslw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6723
{
6724
    TCGv_i32 t0;
6725
    int l1, l2;
6726

    
6727
    l1 = gen_new_label();
6728
    l2 = gen_new_label();
6729
    t0 = tcg_temp_local_new_i32();
6730
    /* No error here: 6 bits are used */
6731
    tcg_gen_andi_i32(t0, arg2, 0x3F);
6732
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6733
    tcg_gen_shl_i32(ret, arg1, t0);
6734
    tcg_gen_br(l2);
6735
    gen_set_label(l1);
6736
    tcg_gen_movi_i32(ret, 0);
6737
    tcg_gen_br(l2);
6738
    tcg_temp_free_i32(t0);
6739
}
6740
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
6741
static always_inline void gen_op_evrlw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6742
{
6743
    TCGv_i32 t0 = tcg_temp_new_i32();
6744
    tcg_gen_andi_i32(t0, arg2, 0x1F);
6745
    tcg_gen_rotl_i32(ret, arg1, t0);
6746
    tcg_temp_free_i32(t0);
6747
}
6748
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
6749
static always_inline void gen_evmergehi (DisasContext *ctx)
6750
{
6751
    if (unlikely(!ctx->spe_enabled)) {
6752
        gen_exception(ctx, POWERPC_EXCP_APU);
6753
        return;
6754
    }
6755
#if defined(TARGET_PPC64)
6756
    TCGv t0 = tcg_temp_new();
6757
    TCGv t1 = tcg_temp_new();
6758
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6759
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6760
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6761
    tcg_temp_free(t0);
6762
    tcg_temp_free(t1);
6763
#else
6764
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6765
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6766
#endif
6767
}
6768
GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
6769
static always_inline void gen_op_evsubf (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6770
{
6771
    tcg_gen_sub_i32(ret, arg2, arg1);
6772
}
6773
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
6774

    
6775
/* SPE arithmetic immediate */
6776
#if defined(TARGET_PPC64)
6777
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
6778
static always_inline void gen_##name (DisasContext *ctx)                      \
6779
{                                                                             \
6780
    if (unlikely(!ctx->spe_enabled)) {                                        \
6781
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6782
        return;                                                               \
6783
    }                                                                         \
6784
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6785
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6786
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6787
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]);                      \
6788
    tcg_op(t0, t0, rA(ctx->opcode));                                          \
6789
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
6790
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6791
    tcg_temp_free_i64(t2);                                                    \
6792
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
6793
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6794
    tcg_temp_free_i32(t0);                                                    \
6795
    tcg_temp_free_i32(t1);                                                    \
6796
}
6797
#else
6798
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
6799
static always_inline void gen_##name (DisasContext *ctx)                      \
6800
{                                                                             \
6801
    if (unlikely(!ctx->spe_enabled)) {                                        \
6802
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6803
        return;                                                               \
6804
    }                                                                         \
6805
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],                \
6806
           rA(ctx->opcode));                                                  \
6807
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)],              \
6808
           rA(ctx->opcode));                                                  \
6809
}
6810
#endif
6811
GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
6812
GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
6813

    
6814
/* SPE comparison */
6815
#if defined(TARGET_PPC64)
6816
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
6817
static always_inline void gen_##name (DisasContext *ctx)                      \
6818
{                                                                             \
6819
    if (unlikely(!ctx->spe_enabled)) {                                        \
6820
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6821
        return;                                                               \
6822
    }                                                                         \
6823
    int l1 = gen_new_label();                                                 \
6824
    int l2 = gen_new_label();                                                 \
6825
    int l3 = gen_new_label();                                                 \
6826
    int l4 = gen_new_label();                                                 \
6827
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6828
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6829
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6830
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6831
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]);                      \
6832
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l1);                                 \
6833
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
6834
    tcg_gen_br(l2);                                                           \
6835
    gen_set_label(l1);                                                        \
6836
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
6837
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
6838
    gen_set_label(l2);                                                        \
6839
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
6840
    tcg_gen_trunc_i64_i32(t0, t2);                                            \
6841
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
6842
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6843
    tcg_temp_free_i64(t2);                                                    \
6844
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l3);                                 \
6845
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
6846
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
6847
    tcg_gen_br(l4);                                                           \
6848
    gen_set_label(l3);                                                        \
6849
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
6850
                    CRF_CH | CRF_CH_OR_CL);                                   \
6851
    gen_set_label(l4);                                                        \
6852
    tcg_temp_free_i32(t0);                                                    \
6853
    tcg_temp_free_i32(t1);                                                    \
6854
}
6855
#else
6856
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
6857
static always_inline void gen_##name (DisasContext *ctx)                      \
6858
{                                                                             \
6859
    if (unlikely(!ctx->spe_enabled)) {                                        \
6860
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6861
        return;                                                               \
6862
    }                                                                         \
6863
    int l1 = gen_new_label();                                                 \
6864
    int l2 = gen_new_label();                                                 \
6865
    int l3 = gen_new_label();                                                 \
6866
    int l4 = gen_new_label();                                                 \
6867
                                                                              \
6868
    tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)],                    \
6869
                       cpu_gpr[rB(ctx->opcode)], l1);                         \
6870
    tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0);                           \
6871
    tcg_gen_br(l2);                                                           \
6872
    gen_set_label(l1);                                                        \
6873
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
6874
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
6875
    gen_set_label(l2);                                                        \
6876
    tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)],                   \
6877
                       cpu_gprh[rB(ctx->opcode)], l3);                        \
6878
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
6879
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
6880
    tcg_gen_br(l4);                                                           \
6881
    gen_set_label(l3);                                                        \
6882
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
6883
                    CRF_CH | CRF_CH_OR_CL);                                   \
6884
    gen_set_label(l4);                                                        \
6885
}
6886
#endif
6887
GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
6888
GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
6889
GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
6890
GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
6891
GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
6892

    
6893
/* SPE misc */
6894
static always_inline void gen_brinc (DisasContext *ctx)
6895
{
6896
    /* Note: brinc is usable even if SPE is disabled */
6897
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
6898
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6899
}
6900
static always_inline void gen_evmergelo (DisasContext *ctx)
6901
{
6902
    if (unlikely(!ctx->spe_enabled)) {
6903
        gen_exception(ctx, POWERPC_EXCP_APU);
6904
        return;
6905
    }
6906
#if defined(TARGET_PPC64)
6907
    TCGv t0 = tcg_temp_new();
6908
    TCGv t1 = tcg_temp_new();
6909
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6910
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6911
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6912
    tcg_temp_free(t0);
6913
    tcg_temp_free(t1);
6914
#else
6915
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6916
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6917
#endif
6918
}
6919
static always_inline void gen_evmergehilo (DisasContext *ctx)
6920
{
6921
    if (unlikely(!ctx->spe_enabled)) {
6922
        gen_exception(ctx, POWERPC_EXCP_APU);
6923
        return;
6924
    }
6925
#if defined(TARGET_PPC64)
6926
    TCGv t0 = tcg_temp_new();
6927
    TCGv t1 = tcg_temp_new();
6928
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6929
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6930
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6931
    tcg_temp_free(t0);
6932
    tcg_temp_free(t1);
6933
#else
6934
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6935
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6936
#endif
6937
}
6938
static always_inline void gen_evmergelohi (DisasContext *ctx)
6939
{
6940
    if (unlikely(!ctx->spe_enabled)) {
6941
        gen_exception(ctx, POWERPC_EXCP_APU);
6942
        return;
6943
    }
6944
#if defined(TARGET_PPC64)
6945
    TCGv t0 = tcg_temp_new();
6946
    TCGv t1 = tcg_temp_new();
6947
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6948
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6949
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6950
    tcg_temp_free(t0);
6951
    tcg_temp_free(t1);
6952
#else
6953
    if (rD(ctx->opcode) == rA(ctx->opcode)) {
6954
        TCGv_i32 tmp = tcg_temp_new_i32();
6955
        tcg_gen_mov_i32(tmp, cpu_gpr[rA(ctx->opcode)]);
6956
        tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6957
        tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], tmp);
6958
        tcg_temp_free_i32(tmp);
6959
    } else {
6960
        tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6961
        tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6962
    }
6963
#endif
6964
}
6965
static always_inline void gen_evsplati (DisasContext *ctx)
6966
{
6967
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 11)) >> 27;
6968

    
6969
#if defined(TARGET_PPC64)
6970
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
6971
#else
6972
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6973
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6974
#endif
6975
}
6976
static always_inline void gen_evsplatfi (DisasContext *ctx)
6977
{
6978
    uint64_t imm = rA(ctx->opcode) << 11;
6979

    
6980
#if defined(TARGET_PPC64)
6981
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
6982
#else
6983
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6984
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6985
#endif
6986
}
6987

    
6988
static always_inline void gen_evsel (DisasContext *ctx)
6989
{
6990
    int l1 = gen_new_label();
6991
    int l2 = gen_new_label();
6992
    int l3 = gen_new_label();
6993
    int l4 = gen_new_label();
6994
    TCGv_i32 t0 = tcg_temp_local_new_i32();
6995
#if defined(TARGET_PPC64)
6996
    TCGv t1 = tcg_temp_local_new();
6997
    TCGv t2 = tcg_temp_local_new();
6998
#endif
6999
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
7000
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
7001
#if defined(TARGET_PPC64)
7002
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7003
#else
7004
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7005
#endif
7006
    tcg_gen_br(l2);
7007
    gen_set_label(l1);
7008
#if defined(TARGET_PPC64)
7009
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7010
#else
7011
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7012
#endif
7013
    gen_set_label(l2);
7014
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
7015
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
7016
#if defined(TARGET_PPC64)
7017
    tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
7018
#else
7019
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7020
#endif
7021
    tcg_gen_br(l4);
7022
    gen_set_label(l3);
7023
#if defined(TARGET_PPC64)
7024
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
7025
#else
7026
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7027
#endif
7028
    gen_set_label(l4);
7029
    tcg_temp_free_i32(t0);
7030
#if defined(TARGET_PPC64)
7031
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
7032
    tcg_temp_free(t1);
7033
    tcg_temp_free(t2);
7034
#endif
7035
}
7036

    
7037
static void gen_evsel0(DisasContext *ctx)
7038
{
7039
    gen_evsel(ctx);
7040
}
7041

    
7042
static void gen_evsel1(DisasContext *ctx)
7043
{
7044
    gen_evsel(ctx);
7045
}
7046

    
7047
static void gen_evsel2(DisasContext *ctx)
7048
{
7049
    gen_evsel(ctx);
7050
}
7051

    
7052
static void gen_evsel3(DisasContext *ctx)
7053
{
7054
    gen_evsel(ctx);
7055
}
7056

    
7057
GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE); ////
7058
GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE);
7059
GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE); ////
7060
GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE);
7061
GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE); ////
7062
GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE); ////
7063
GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE); ////
7064
GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE); //
7065
GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE); ////
7066
GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE); ////
7067
GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE); ////
7068
GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE); ////
7069
GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE); ////
7070
GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE); ////
7071
GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE); ////
7072
GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE);
7073
GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE); ////
7074
GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE);
7075
GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE); //
7076
GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE);
7077
GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE); ////
7078
GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE); ////
7079
GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE); ////
7080
GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE); ////
7081
GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE); ////
7082

    
7083
/* SPE load and stores */
7084
static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, TCGv EA, int sh)
7085
{
7086
    target_ulong uimm = rB(ctx->opcode);
7087

    
7088
    if (rA(ctx->opcode) == 0) {
7089
        tcg_gen_movi_tl(EA, uimm << sh);
7090
    } else {
7091
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
7092
#if defined(TARGET_PPC64)
7093
        if (!ctx->sf_mode) {
7094
            tcg_gen_ext32u_tl(EA, EA);
7095
        }
7096
#endif
7097
    }
7098
}
7099

    
7100
static always_inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7101
{
7102
#if defined(TARGET_PPC64)
7103
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7104
#else
7105
    TCGv_i64 t0 = tcg_temp_new_i64();
7106
    gen_qemu_ld64(ctx, t0, addr);
7107
    tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
7108
    tcg_gen_shri_i64(t0, t0, 32);
7109
    tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
7110
    tcg_temp_free_i64(t0);
7111
#endif
7112
}
7113

    
7114
static always_inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7115
{
7116
#if defined(TARGET_PPC64)
7117
    TCGv t0 = tcg_temp_new();
7118
    gen_qemu_ld32u(ctx, t0, addr);
7119
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7120
    gen_addr_add(ctx, addr, addr, 4);
7121
    gen_qemu_ld32u(ctx, t0, addr);
7122
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7123
    tcg_temp_free(t0);
7124
#else
7125
    gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7126
    gen_addr_add(ctx, addr, addr, 4);
7127
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7128
#endif
7129
}
7130

    
7131
static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7132
{
7133
    TCGv t0 = tcg_temp_new();
7134
#if defined(TARGET_PPC64)
7135
    gen_qemu_ld16u(ctx, t0, addr);
7136
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7137
    gen_addr_add(ctx, addr, addr, 2);
7138
    gen_qemu_ld16u(ctx, t0, addr);
7139
    tcg_gen_shli_tl(t0, t0, 32);
7140
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7141
    gen_addr_add(ctx, addr, addr, 2);
7142
    gen_qemu_ld16u(ctx, t0, addr);
7143
    tcg_gen_shli_tl(t0, t0, 16);
7144
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7145
    gen_addr_add(ctx, addr, addr, 2);
7146
    gen_qemu_ld16u(ctx, t0, addr);
7147
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7148
#else
7149
    gen_qemu_ld16u(ctx, t0, addr);
7150
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7151
    gen_addr_add(ctx, addr, addr, 2);
7152
    gen_qemu_ld16u(ctx, t0, addr);
7153
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7154
    gen_addr_add(ctx, addr, addr, 2);
7155
    gen_qemu_ld16u(ctx, t0, addr);
7156
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7157
    gen_addr_add(ctx, addr, addr, 2);
7158
    gen_qemu_ld16u(ctx, t0, addr);
7159
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7160
#endif
7161
    tcg_temp_free(t0);
7162
}
7163

    
7164
static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7165
{
7166
    TCGv t0 = tcg_temp_new();
7167
    gen_qemu_ld16u(ctx, t0, addr);
7168
#if defined(TARGET_PPC64)
7169
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7170
    tcg_gen_shli_tl(t0, t0, 16);
7171
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7172
#else
7173
    tcg_gen_shli_tl(t0, t0, 16);
7174
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7175
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7176
#endif
7177
    tcg_temp_free(t0);
7178
}
7179

    
7180
static always_inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
7181
{
7182
    TCGv t0 = tcg_temp_new();
7183
    gen_qemu_ld16u(ctx, t0, addr);
7184
#if defined(TARGET_PPC64)
7185
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7186
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7187
#else
7188
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7189
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7190
#endif
7191
    tcg_temp_free(t0);
7192
}
7193

    
7194
static always_inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7195
{
7196
    TCGv t0 = tcg_temp_new();
7197
    gen_qemu_ld16s(ctx, t0, addr);
7198
#if defined(TARGET_PPC64)
7199
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7200
    tcg_gen_ext32u_tl(t0, t0);
7201
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7202
#else
7203
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7204
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7205
#endif
7206
    tcg_temp_free(t0);
7207
}
7208

    
7209
static always_inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7210
{
7211
    TCGv t0 = tcg_temp_new();
7212
#if defined(TARGET_PPC64)
7213
    gen_qemu_ld16u(ctx, t0, addr);
7214
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7215
    gen_addr_add(ctx, addr, addr, 2);
7216
    gen_qemu_ld16u(ctx, t0, addr);
7217
    tcg_gen_shli_tl(t0, t0, 16);
7218
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7219
#else
7220
    gen_qemu_ld16u(ctx, t0, addr);
7221
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7222
    gen_addr_add(ctx, addr, addr, 2);
7223
    gen_qemu_ld16u(ctx, t0, addr);
7224
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7225
#endif
7226
    tcg_temp_free(t0);
7227
}
7228

    
7229
static always_inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7230
{
7231
#if defined(TARGET_PPC64)
7232
    TCGv t0 = tcg_temp_new();
7233
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7234
    gen_addr_add(ctx, addr, addr, 2);
7235
    gen_qemu_ld16u(ctx, t0, addr);
7236
    tcg_gen_shli_tl(t0, t0, 32);
7237
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7238
    tcg_temp_free(t0);
7239
#else
7240
    gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7241
    gen_addr_add(ctx, addr, addr, 2);
7242
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7243
#endif
7244
}
7245

    
7246
static always_inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7247
{
7248
#if defined(TARGET_PPC64)
7249
    TCGv t0 = tcg_temp_new();
7250
    gen_qemu_ld16s(ctx, t0, addr);
7251
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
7252
    gen_addr_add(ctx, addr, addr, 2);
7253
    gen_qemu_ld16s(ctx, t0, addr);
7254
    tcg_gen_shli_tl(t0, t0, 32);
7255
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7256
    tcg_temp_free(t0);
7257
#else
7258
    gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7259
    gen_addr_add(ctx, addr, addr, 2);
7260
    gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7261
#endif
7262
}
7263

    
7264
static always_inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7265
{
7266
    TCGv t0 = tcg_temp_new();
7267
    gen_qemu_ld32u(ctx, t0, addr);
7268
#if defined(TARGET_PPC64)
7269
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7270
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7271
#else
7272
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7273
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7274
#endif
7275
    tcg_temp_free(t0);
7276
}
7277

    
7278
static always_inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7279
{
7280
    TCGv t0 = tcg_temp_new();
7281
#if defined(TARGET_PPC64)
7282
    gen_qemu_ld16u(ctx, t0, addr);
7283
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7284
    tcg_gen_shli_tl(t0, t0, 32);
7285
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7286
    gen_addr_add(ctx, addr, addr, 2);
7287
    gen_qemu_ld16u(ctx, t0, addr);
7288
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7289
    tcg_gen_shli_tl(t0, t0, 16);
7290
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7291
#else
7292
    gen_qemu_ld16u(ctx, t0, addr);
7293
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7294
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7295
    gen_addr_add(ctx, addr, addr, 2);
7296
    gen_qemu_ld16u(ctx, t0, addr);
7297
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7298
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7299
#endif
7300
    tcg_temp_free(t0);
7301
}
7302

    
7303
static always_inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7304
{
7305
#if defined(TARGET_PPC64)
7306
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7307
#else
7308
    TCGv_i64 t0 = tcg_temp_new_i64();
7309
    tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
7310
    gen_qemu_st64(ctx, t0, addr);
7311
    tcg_temp_free_i64(t0);
7312
#endif
7313
}
7314

    
7315
static always_inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7316
{
7317
#if defined(TARGET_PPC64)
7318
    TCGv t0 = tcg_temp_new();
7319
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7320
    gen_qemu_st32(ctx, t0, addr);
7321
    tcg_temp_free(t0);
7322
#else
7323
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7324
#endif
7325
    gen_addr_add(ctx, addr, addr, 4);
7326
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7327
}
7328

    
7329
static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7330
{
7331
    TCGv t0 = tcg_temp_new();
7332
#if defined(TARGET_PPC64)
7333
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7334
#else
7335
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7336
#endif
7337
    gen_qemu_st16(ctx, t0, addr);
7338
    gen_addr_add(ctx, addr, addr, 2);
7339
#if defined(TARGET_PPC64)
7340
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7341
    gen_qemu_st16(ctx, t0, addr);
7342
#else
7343
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7344
#endif
7345
    gen_addr_add(ctx, addr, addr, 2);
7346
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7347
    gen_qemu_st16(ctx, t0, addr);
7348
    tcg_temp_free(t0);
7349
    gen_addr_add(ctx, addr, addr, 2);
7350
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7351
}
7352

    
7353
static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7354
{
7355
    TCGv t0 = tcg_temp_new();
7356
#if defined(TARGET_PPC64)
7357
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7358
#else
7359
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7360
#endif
7361
    gen_qemu_st16(ctx, t0, addr);
7362
    gen_addr_add(ctx, addr, addr, 2);
7363
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7364
    gen_qemu_st16(ctx, t0, addr);
7365
    tcg_temp_free(t0);
7366
}
7367

    
7368
static always_inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7369
{
7370
#if defined(TARGET_PPC64)
7371
    TCGv t0 = tcg_temp_new();
7372
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7373
    gen_qemu_st16(ctx, t0, addr);
7374
    tcg_temp_free(t0);
7375
#else
7376
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7377
#endif
7378
    gen_addr_add(ctx, addr, addr, 2);
7379
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7380
}
7381

    
7382
static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7383
{
7384
#if defined(TARGET_PPC64)
7385
    TCGv t0 = tcg_temp_new();
7386
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7387
    gen_qemu_st32(ctx, t0, addr);
7388
    tcg_temp_free(t0);
7389
#else
7390
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7391
#endif
7392
}
7393

    
7394
static always_inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7395
{
7396
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7397
}
7398

    
7399
#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
7400
static void glue(gen_, name)(DisasContext *ctx)                                       \
7401
{                                                                             \
7402
    TCGv t0;                                                                  \
7403
    if (unlikely(!ctx->spe_enabled)) {                                        \
7404
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7405
        return;                                                               \
7406
    }                                                                         \
7407
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7408
    t0 = tcg_temp_new();                                                      \
7409
    if (Rc(ctx->opcode)) {                                                    \
7410
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7411
    } else {                                                                  \
7412
        gen_addr_reg_index(ctx, t0);                                          \
7413
    }                                                                         \
7414
    gen_op_##name(ctx, t0);                                                   \
7415
    tcg_temp_free(t0);                                                        \
7416
}
7417

    
7418
GEN_SPEOP_LDST(evldd, 0x00, 3);
7419
GEN_SPEOP_LDST(evldw, 0x01, 3);
7420
GEN_SPEOP_LDST(evldh, 0x02, 3);
7421
GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
7422
GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
7423
GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
7424
GEN_SPEOP_LDST(evlwhe, 0x08, 2);
7425
GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
7426
GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
7427
GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
7428
GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
7429

    
7430
GEN_SPEOP_LDST(evstdd, 0x10, 3);
7431
GEN_SPEOP_LDST(evstdw, 0x11, 3);
7432
GEN_SPEOP_LDST(evstdh, 0x12, 3);
7433
GEN_SPEOP_LDST(evstwhe, 0x18, 2);
7434
GEN_SPEOP_LDST(evstwho, 0x1A, 2);
7435
GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
7436
GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
7437

    
7438
/* Multiply and add - TODO */
7439
#if 0
7440
GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0x00000000, PPC_SPE);
7441
GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0x00000000, PPC_SPE);
7442
GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, PPC_SPE);
7443
GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0x00000000, PPC_SPE);
7444
GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, PPC_SPE);
7445
GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0x00000000, PPC_SPE);
7446
GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0x00000000, PPC_SPE);
7447
GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0x00000000, PPC_SPE);
7448
GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, PPC_SPE);
7449
GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0x00000000, PPC_SPE);
7450
GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, PPC_SPE);
7451
GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0x00000000, PPC_SPE);
7452

7453
GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
7454
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
7455
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
7456
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
7457
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
7458
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
7459
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
7460
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
7461
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
7462
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
7463
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
7464
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
7465
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
7466
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
7467

7468
GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
7469
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
7470
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
7471
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
7472
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
7473
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
7474

7475
GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
7476
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
7477
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
7478
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
7479
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
7480
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
7481
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
7482
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
7483
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
7484
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
7485
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
7486
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
7487

7488
GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
7489
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
7490
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
7491
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
7492
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
7493

7494
GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
7495
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
7496
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
7497
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
7498
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
7499
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
7500
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
7501
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
7502
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
7503
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
7504
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
7505
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
7506

7507
GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, PPC_SPE);
7508
GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, PPC_SPE);
7509
GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0x00000000, PPC_SPE);
7510
GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, PPC_SPE);
7511
GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0x00000000, PPC_SPE);
7512
#endif
7513

    
7514
/***                      SPE floating-point extension                     ***/
7515
#if defined(TARGET_PPC64)
7516
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
7517
static always_inline void gen_##name (DisasContext *ctx)                      \
7518
{                                                                             \
7519
    TCGv_i32 t0;                                                              \
7520
    TCGv t1;                                                                  \
7521
    t0 = tcg_temp_new_i32();                                                  \
7522
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
7523
    gen_helper_##name(t0, t0);                                                \
7524
    t1 = tcg_temp_new();                                                      \
7525
    tcg_gen_extu_i32_tl(t1, t0);                                              \
7526
    tcg_temp_free_i32(t0);                                                    \
7527
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7528
                    0xFFFFFFFF00000000ULL);                                   \
7529
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
7530
    tcg_temp_free(t1);                                                        \
7531
}
7532
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
7533
static always_inline void gen_##name (DisasContext *ctx)                      \
7534
{                                                                             \
7535
    TCGv_i32 t0;                                                              \
7536
    TCGv t1;                                                                  \
7537
    t0 = tcg_temp_new_i32();                                                  \
7538
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
7539
    t1 = tcg_temp_new();                                                      \
7540
    tcg_gen_extu_i32_tl(t1, t0);                                              \
7541
    tcg_temp_free_i32(t0);                                                    \
7542
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7543
                    0xFFFFFFFF00000000ULL);                                   \
7544
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
7545
    tcg_temp_free(t1);                                                        \
7546
}
7547
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
7548
static always_inline void gen_##name (DisasContext *ctx)                      \
7549
{                                                                             \
7550
    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
7551
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
7552
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
7553
    tcg_temp_free_i32(t0);                                                    \
7554
}
7555
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
7556
static always_inline void gen_##name (DisasContext *ctx)                      \
7557
{                                                                             \
7558
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7559
}
7560
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
7561
static always_inline void gen_##name (DisasContext *ctx)                      \
7562
{                                                                             \
7563
    TCGv_i32 t0, t1;                                                          \
7564
    TCGv_i64 t2;                                                              \
7565
    if (unlikely(!ctx->spe_enabled)) {                                        \
7566
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7567
        return;                                                               \
7568
    }                                                                         \
7569
    t0 = tcg_temp_new_i32();                                                  \
7570
    t1 = tcg_temp_new_i32();                                                  \
7571
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
7572
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
7573
    gen_helper_##name(t0, t0, t1);                                            \
7574
    tcg_temp_free_i32(t1);                                                    \
7575
    t2 = tcg_temp_new();                                                      \
7576
    tcg_gen_extu_i32_tl(t2, t0);                                              \
7577
    tcg_temp_free_i32(t0);                                                    \
7578
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7579
                    0xFFFFFFFF00000000ULL);                                   \
7580
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2);    \
7581
    tcg_temp_free(t2);                                                        \
7582
}
7583
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
7584
static always_inline void gen_##name (DisasContext *ctx)                      \
7585
{                                                                             \
7586
    if (unlikely(!ctx->spe_enabled)) {                                        \
7587
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7588
        return;                                                               \
7589
    }                                                                         \
7590
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],     \
7591
                      cpu_gpr[rB(ctx->opcode)]);                              \
7592
}
7593
#define GEN_SPEFPUOP_COMP_32(name)                                            \
7594
static always_inline void gen_##name (DisasContext *ctx)                      \
7595
{                                                                             \
7596
    TCGv_i32 t0, t1;                                                          \
7597
    if (unlikely(!ctx->spe_enabled)) {                                        \
7598
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7599
        return;                                                               \
7600
    }                                                                         \
7601
    t0 = tcg_temp_new_i32();                                                  \
7602
    t1 = tcg_temp_new_i32();                                                  \
7603
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
7604
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
7605
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
7606
    tcg_temp_free_i32(t0);                                                    \
7607
    tcg_temp_free_i32(t1);                                                    \
7608
}
7609
#define GEN_SPEFPUOP_COMP_64(name)                                            \
7610
static always_inline void gen_##name (DisasContext *ctx)                      \
7611
{                                                                             \
7612
    if (unlikely(!ctx->spe_enabled)) {                                        \
7613
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7614
        return;                                                               \
7615
    }                                                                         \
7616
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
7617
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7618
}
7619
#else
7620
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
7621
static always_inline void gen_##name (DisasContext *ctx)                      \
7622
{                                                                             \
7623
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7624
}
7625
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
7626
static always_inline void gen_##name (DisasContext *ctx)                      \
7627
{                                                                             \
7628
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7629
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
7630
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
7631
    tcg_temp_free_i64(t0);                                                    \
7632
}
7633
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
7634
static always_inline void gen_##name (DisasContext *ctx)                      \
7635
{                                                                             \
7636
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7637
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
7638
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7639
    tcg_temp_free_i64(t0);                                                    \
7640
}
7641
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
7642
static always_inline void gen_##name (DisasContext *ctx)                      \
7643
{                                                                             \
7644
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7645
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
7646
    gen_helper_##name(t0, t0);                                                \
7647
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7648
    tcg_temp_free_i64(t0);                                                    \
7649
}
7650
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
7651
static always_inline void gen_##name (DisasContext *ctx)                      \
7652
{                                                                             \
7653
    if (unlikely(!ctx->spe_enabled)) {                                        \
7654
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7655
        return;                                                               \
7656
    }                                                                         \
7657
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)],                               \
7658
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7659
}
7660
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
7661
static always_inline void gen_##name (DisasContext *ctx)                      \
7662
{                                                                             \
7663
    TCGv_i64 t0, t1;                                                          \
7664
    if (unlikely(!ctx->spe_enabled)) {                                        \
7665
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7666
        return;                                                               \
7667
    }                                                                         \
7668
    t0 = tcg_temp_new_i64();                                                  \
7669
    t1 = tcg_temp_new_i64();                                                  \
7670
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
7671
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
7672
    gen_helper_##name(t0, t0, t1);                                            \
7673
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7674
    tcg_temp_free_i64(t0);                                                    \
7675
    tcg_temp_free_i64(t1);                                                    \
7676
}
7677
#define GEN_SPEFPUOP_COMP_32(name)                                            \
7678
static always_inline void gen_##name (DisasContext *ctx)                      \
7679
{                                                                             \
7680
    if (unlikely(!ctx->spe_enabled)) {                                        \
7681
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7682
        return;                                                               \
7683
    }                                                                         \
7684
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
7685
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7686
}
7687
#define GEN_SPEFPUOP_COMP_64(name)                                            \
7688
static always_inline void gen_##name (DisasContext *ctx)                      \
7689
{                                                                             \
7690
    TCGv_i64 t0, t1;                                                          \
7691
    if (unlikely(!ctx->spe_enabled)) {                                        \
7692
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7693
        return;                                                               \
7694
    }                                                                         \
7695
    t0 = tcg_temp_new_i64();                                                  \
7696
    t1 = tcg_temp_new_i64();                                                  \
7697
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
7698
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
7699
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
7700
    tcg_temp_free_i64(t0);                                                    \
7701
    tcg_temp_free_i64(t1);                                                    \
7702
}
7703
#endif
7704

    
7705
/* Single precision floating-point vectors operations */
7706
/* Arithmetic */
7707
GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
7708
GEN_SPEFPUOP_ARITH2_64_64(evfssub);
7709
GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
7710
GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
7711
static always_inline void gen_evfsabs (DisasContext *ctx)
7712
{
7713
    if (unlikely(!ctx->spe_enabled)) {
7714
        gen_exception(ctx, POWERPC_EXCP_APU);
7715
        return;
7716
    }
7717
#if defined(TARGET_PPC64)
7718
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
7719
#else
7720
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
7721
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7722
#endif
7723
}
7724
static always_inline void gen_evfsnabs (DisasContext *ctx)
7725
{
7726
    if (unlikely(!ctx->spe_enabled)) {
7727
        gen_exception(ctx, POWERPC_EXCP_APU);
7728
        return;
7729
    }
7730
#if defined(TARGET_PPC64)
7731
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7732
#else
7733
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7734
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7735
#endif
7736
}
7737
static always_inline void gen_evfsneg (DisasContext *ctx)
7738
{
7739
    if (unlikely(!ctx->spe_enabled)) {
7740
        gen_exception(ctx, POWERPC_EXCP_APU);
7741
        return;
7742
    }
7743
#if defined(TARGET_PPC64)
7744
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7745
#else
7746
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7747
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7748
#endif
7749
}
7750

    
7751
/* Conversion */
7752
GEN_SPEFPUOP_CONV_64_64(evfscfui);
7753
GEN_SPEFPUOP_CONV_64_64(evfscfsi);
7754
GEN_SPEFPUOP_CONV_64_64(evfscfuf);
7755
GEN_SPEFPUOP_CONV_64_64(evfscfsf);
7756
GEN_SPEFPUOP_CONV_64_64(evfsctui);
7757
GEN_SPEFPUOP_CONV_64_64(evfsctsi);
7758
GEN_SPEFPUOP_CONV_64_64(evfsctuf);
7759
GEN_SPEFPUOP_CONV_64_64(evfsctsf);
7760
GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
7761
GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
7762

    
7763
/* Comparison */
7764
GEN_SPEFPUOP_COMP_64(evfscmpgt);
7765
GEN_SPEFPUOP_COMP_64(evfscmplt);
7766
GEN_SPEFPUOP_COMP_64(evfscmpeq);
7767
GEN_SPEFPUOP_COMP_64(evfststgt);
7768
GEN_SPEFPUOP_COMP_64(evfststlt);
7769
GEN_SPEFPUOP_COMP_64(evfststeq);
7770

    
7771
/* Opcodes definitions */
7772
GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
7773
GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
7774
GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
7775
GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
7776
GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7777
GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7778
GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7779
GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7780
GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7781
GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7782
GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7783
GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7784
GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7785
GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7786

    
7787
/* Single precision floating-point operations */
7788
/* Arithmetic */
7789
GEN_SPEFPUOP_ARITH2_32_32(efsadd);
7790
GEN_SPEFPUOP_ARITH2_32_32(efssub);
7791
GEN_SPEFPUOP_ARITH2_32_32(efsmul);
7792
GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
7793
static always_inline void gen_efsabs (DisasContext *ctx)
7794
{
7795
    if (unlikely(!ctx->spe_enabled)) {
7796
        gen_exception(ctx, POWERPC_EXCP_APU);
7797
        return;
7798
    }
7799
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
7800
}
7801
static always_inline void gen_efsnabs (DisasContext *ctx)
7802
{
7803
    if (unlikely(!ctx->spe_enabled)) {
7804
        gen_exception(ctx, POWERPC_EXCP_APU);
7805
        return;
7806
    }
7807
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7808
}
7809
static always_inline void gen_efsneg (DisasContext *ctx)
7810
{
7811
    if (unlikely(!ctx->spe_enabled)) {
7812
        gen_exception(ctx, POWERPC_EXCP_APU);
7813
        return;
7814
    }
7815
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7816
}
7817

    
7818
/* Conversion */
7819
GEN_SPEFPUOP_CONV_32_32(efscfui);
7820
GEN_SPEFPUOP_CONV_32_32(efscfsi);
7821
GEN_SPEFPUOP_CONV_32_32(efscfuf);
7822
GEN_SPEFPUOP_CONV_32_32(efscfsf);
7823
GEN_SPEFPUOP_CONV_32_32(efsctui);
7824
GEN_SPEFPUOP_CONV_32_32(efsctsi);
7825
GEN_SPEFPUOP_CONV_32_32(efsctuf);
7826
GEN_SPEFPUOP_CONV_32_32(efsctsf);
7827
GEN_SPEFPUOP_CONV_32_32(efsctuiz);
7828
GEN_SPEFPUOP_CONV_32_32(efsctsiz);
7829
GEN_SPEFPUOP_CONV_32_64(efscfd);
7830

    
7831
/* Comparison */
7832
GEN_SPEFPUOP_COMP_32(efscmpgt);
7833
GEN_SPEFPUOP_COMP_32(efscmplt);
7834
GEN_SPEFPUOP_COMP_32(efscmpeq);
7835
GEN_SPEFPUOP_COMP_32(efststgt);
7836
GEN_SPEFPUOP_COMP_32(efststlt);
7837
GEN_SPEFPUOP_COMP_32(efststeq);
7838

    
7839
/* Opcodes definitions */
7840
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
7841
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
7842
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
7843
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
7844
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7845
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7846
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7847
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7848
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7849
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7850
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7851
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7852
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7853
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7854

    
7855
/* Double precision floating-point operations */
7856
/* Arithmetic */
7857
GEN_SPEFPUOP_ARITH2_64_64(efdadd);
7858
GEN_SPEFPUOP_ARITH2_64_64(efdsub);
7859
GEN_SPEFPUOP_ARITH2_64_64(efdmul);
7860
GEN_SPEFPUOP_ARITH2_64_64(efddiv);
7861
static always_inline void gen_efdabs (DisasContext *ctx)
7862
{
7863
    if (unlikely(!ctx->spe_enabled)) {
7864
        gen_exception(ctx, POWERPC_EXCP_APU);
7865
        return;
7866
    }
7867
#if defined(TARGET_PPC64)
7868
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
7869
#else
7870
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7871
#endif
7872
}
7873
static always_inline void gen_efdnabs (DisasContext *ctx)
7874
{
7875
    if (unlikely(!ctx->spe_enabled)) {
7876
        gen_exception(ctx, POWERPC_EXCP_APU);
7877
        return;
7878
    }
7879
#if defined(TARGET_PPC64)
7880
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7881
#else
7882
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7883
#endif
7884
}
7885
static always_inline void gen_efdneg (DisasContext *ctx)
7886
{
7887
    if (unlikely(!ctx->spe_enabled)) {
7888
        gen_exception(ctx, POWERPC_EXCP_APU);
7889
        return;
7890
    }
7891
#if defined(TARGET_PPC64)
7892
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7893
#else
7894
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7895
#endif
7896
}
7897

    
7898
/* Conversion */
7899
GEN_SPEFPUOP_CONV_64_32(efdcfui);
7900
GEN_SPEFPUOP_CONV_64_32(efdcfsi);
7901
GEN_SPEFPUOP_CONV_64_32(efdcfuf);
7902
GEN_SPEFPUOP_CONV_64_32(efdcfsf);
7903
GEN_SPEFPUOP_CONV_32_64(efdctui);
7904
GEN_SPEFPUOP_CONV_32_64(efdctsi);
7905
GEN_SPEFPUOP_CONV_32_64(efdctuf);
7906
GEN_SPEFPUOP_CONV_32_64(efdctsf);
7907
GEN_SPEFPUOP_CONV_32_64(efdctuiz);
7908
GEN_SPEFPUOP_CONV_32_64(efdctsiz);
7909
GEN_SPEFPUOP_CONV_64_32(efdcfs);
7910
GEN_SPEFPUOP_CONV_64_64(efdcfuid);
7911
GEN_SPEFPUOP_CONV_64_64(efdcfsid);
7912
GEN_SPEFPUOP_CONV_64_64(efdctuidz);
7913
GEN_SPEFPUOP_CONV_64_64(efdctsidz);
7914

    
7915
/* Comparison */
7916
GEN_SPEFPUOP_COMP_64(efdcmpgt);
7917
GEN_SPEFPUOP_COMP_64(efdcmplt);
7918
GEN_SPEFPUOP_COMP_64(efdcmpeq);
7919
GEN_SPEFPUOP_COMP_64(efdtstgt);
7920
GEN_SPEFPUOP_COMP_64(efdtstlt);
7921
GEN_SPEFPUOP_COMP_64(efdtsteq);
7922

    
7923
/* Opcodes definitions */
7924
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
7925
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7926
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
7927
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
7928
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
7929
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7930
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7931
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7932
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7933
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7934
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7935
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7936
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7937
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
7938
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7939
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
7940

    
7941
static opcode_t opcodes[] = {
7942
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
7943
GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
7944
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
7945
GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
7946
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
7947
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
7948
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7949
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7950
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7951
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7952
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
7953
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
7954
GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
7955
GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
7956
GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7957
#if defined(TARGET_PPC64)
7958
GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
7959
#endif
7960
GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
7961
GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
7962
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7963
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7964
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7965
GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
7966
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
7967
GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
7968
GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7969
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7970
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7971
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7972
GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
7973
#if defined(TARGET_PPC64)
7974
GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
7975
#endif
7976
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7977
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7978
GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
7979
GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
7980
GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
7981
GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
7982
GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
7983
#if defined(TARGET_PPC64)
7984
GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
7985
GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
7986
GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
7987
GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
7988
GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
7989
#endif
7990
GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
7991
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
7992
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
7993
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
7994
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
7995
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
7996
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
7997
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
7998
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
7999
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
8000
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT),
8001
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT),
8002
#if defined(TARGET_PPC64)
8003
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
8004
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
8005
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
8006
#endif
8007
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8008
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8009
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
8010
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
8011
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
8012
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
8013
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
8014
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
8015
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES),
8016
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
8017
#if defined(TARGET_PPC64)
8018
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B),
8019
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
8020
#endif
8021
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
8022
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
8023
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8024
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8025
GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
8026
GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
8027
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
8028
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
8029
#if defined(TARGET_PPC64)
8030
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
8031
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
8032
#endif
8033
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
8034
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
8035
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8036
#if defined(TARGET_PPC64)
8037
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
8038
GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
8039
#endif
8040
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
8041
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
8042
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
8043
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
8044
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
8045
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
8046
#if defined(TARGET_PPC64)
8047
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
8048
#endif
8049
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC),
8050
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC),
8051
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
8052
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
8053
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
8054
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE),
8055
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE),
8056
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ),
8057
GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT),
8058
GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
8059
GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
8060
GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
8061
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
8062
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
8063
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
8064
GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
8065
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
8066
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
8067
#if defined(TARGET_PPC64)
8068
GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
8069
GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
8070
             PPC_SEGMENT_64B),
8071
GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
8072
GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
8073
             PPC_SEGMENT_64B),
8074
GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B),
8075
#endif
8076
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
8077
GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
8078
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE),
8079
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
8080
#if defined(TARGET_PPC64)
8081
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
8082
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
8083
#endif
8084
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
8085
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
8086
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
8087
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
8088
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
8089
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
8090
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
8091
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
8092
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
8093
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
8094
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
8095
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8096
GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
8097
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
8098
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
8099
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
8100
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
8101
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
8102
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
8103
GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8104
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
8105
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
8106
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
8107
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
8108
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
8109
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
8110
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
8111
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
8112
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
8113
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
8114
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
8115
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
8116
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
8117
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
8118
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
8119
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
8120
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
8121
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
8122
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
8123
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
8124
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
8125
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
8126
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
8127
GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
8128
GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
8129
GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
8130
GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
8131
GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
8132
GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
8133
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8134
GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8135
GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
8136
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
8137
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8138
GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8139
GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
8140
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
8141
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
8142
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
8143
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
8144
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
8145
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
8146
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
8147
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
8148
GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
8149
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
8150
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
8151
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
8152
GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
8153
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
8154
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
8155
GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE),
8156
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
8157
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
8158
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
8159
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
8160
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
8161
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
8162
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
8163
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
8164
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
8165
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
8166
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
8167
GEN_HANDLER(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, PPC_BOOKE),
8168
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
8169
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE),
8170
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
8171
GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
8172
GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
8173
GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
8174
GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC),
8175
GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
8176
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
8177
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
8178
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
8179
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),
8180

    
8181
#undef GEN_INT_ARITH_ADD
8182
#undef GEN_INT_ARITH_ADD_CONST
8183
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
8184
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
8185
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
8186
                                add_ca, compute_ca, compute_ov)               \
8187
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
8188
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
8189
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
8190
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
8191
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
8192
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
8193
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
8194
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
8195
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
8196
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
8197
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
8198

    
8199
#undef GEN_INT_ARITH_DIVW
8200
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
8201
GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
8202
GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
8203
GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
8204
GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
8205
GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
8206

    
8207
#if defined(TARGET_PPC64)
8208
#undef GEN_INT_ARITH_DIVD
8209
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
8210
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8211
GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
8212
GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
8213
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
8214
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
8215

    
8216
#undef GEN_INT_ARITH_MUL_HELPER
8217
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
8218
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8219
GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
8220
GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
8221
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
8222
#endif
8223

    
8224
#undef GEN_INT_ARITH_SUBF
8225
#undef GEN_INT_ARITH_SUBF_CONST
8226
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
8227
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
8228
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
8229
                                add_ca, compute_ca, compute_ov)               \
8230
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
8231
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
8232
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
8233
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
8234
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
8235
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
8236
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
8237
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
8238
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
8239
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
8240
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
8241

    
8242
#undef GEN_LOGICAL1
8243
#undef GEN_LOGICAL2
8244
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
8245
GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
8246
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
8247
GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
8248
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
8249
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
8250
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
8251
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
8252
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
8253
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
8254
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
8255
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
8256
#if defined(TARGET_PPC64)
8257
GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
8258
#endif
8259

    
8260
#if defined(TARGET_PPC64)
8261
#undef GEN_PPC64_R2
8262
#undef GEN_PPC64_R4
8263
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
8264
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8265
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
8266
             PPC_64B)
8267
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
8268
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8269
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
8270
             PPC_64B),                                                        \
8271
GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
8272
             PPC_64B),                                                        \
8273
GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000,   \
8274
             PPC_64B)
8275
GEN_PPC64_R4(rldicl, 0x1E, 0x00),
8276
GEN_PPC64_R4(rldicr, 0x1E, 0x02),
8277
GEN_PPC64_R4(rldic, 0x1E, 0x04),
8278
GEN_PPC64_R2(rldcl, 0x1E, 0x08),
8279
GEN_PPC64_R2(rldcr, 0x1E, 0x09),
8280
GEN_PPC64_R4(rldimi, 0x1E, 0x06),
8281
#endif
8282

    
8283
#undef _GEN_FLOAT_ACB
8284
#undef GEN_FLOAT_ACB
8285
#undef _GEN_FLOAT_AB
8286
#undef GEN_FLOAT_AB
8287
#undef _GEN_FLOAT_AC
8288
#undef GEN_FLOAT_AC
8289
#undef GEN_FLOAT_B
8290
#undef GEN_FLOAT_BS
8291
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
8292
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
8293
#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
8294
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type),                     \
8295
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type)
8296
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
8297
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8298
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
8299
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type),               \
8300
_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8301
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
8302
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8303
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
8304
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type),               \
8305
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8306
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
8307
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
8308
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
8309
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)
8310

    
8311
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
8312
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
8313
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
8314
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
8315
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
8316
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
8317
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
8318
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
8319
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
8320
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
8321
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
8322
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
8323
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
8324
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
8325
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
8326
#if defined(TARGET_PPC64)
8327
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B),
8328
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B),
8329
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B),
8330
#endif
8331
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
8332
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
8333
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
8334
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
8335
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT),
8336
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT),
8337
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),
8338

    
8339
#undef GEN_LD
8340
#undef GEN_LDU
8341
#undef GEN_LDUX
8342
#undef GEN_LDX
8343
#undef GEN_LDS
8344
#define GEN_LD(name, ldop, opc, type)                                         \
8345
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8346
#define GEN_LDU(name, ldop, opc, type)                                        \
8347
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8348
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
8349
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8350
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
8351
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8352
#define GEN_LDS(name, ldop, op, type)                                         \
8353
GEN_LD(name, ldop, op | 0x20, type)                                           \
8354
GEN_LDU(name, ldop, op | 0x21, type)                                          \
8355
GEN_LDUX(name, ldop, 0x17, op | 0x01, type)                                   \
8356
GEN_LDX(name, ldop, 0x17, op | 0x00, type)
8357

    
8358
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
8359
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
8360
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
8361
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
8362
#if defined(TARGET_PPC64)
8363
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
8364
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
8365
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
8366
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
8367
#endif
8368
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
8369
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
8370

    
8371
#undef GEN_ST
8372
#undef GEN_STU
8373
#undef GEN_STUX
8374
#undef GEN_STX
8375
#undef GEN_STS
8376
#define GEN_ST(name, stop, opc, type)                                         \
8377
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8378
#define GEN_STU(name, stop, opc, type)                                        \
8379
GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
8380
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
8381
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8382
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
8383
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8384
#define GEN_STS(name, stop, op, type)                                         \
8385
GEN_ST(name, stop, op | 0x20, type)                                           \
8386
GEN_STU(name, stop, op | 0x21, type)                                          \
8387
GEN_STUX(name, stop, 0x17, op | 0x01, type)                                   \
8388
GEN_STX(name, stop, 0x17, op | 0x00, type)
8389

    
8390
GEN_STS(stb, st8, 0x06, PPC_INTEGER)
8391
GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
8392
GEN_STS(stw, st32, 0x04, PPC_INTEGER)
8393
#if defined(TARGET_PPC64)
8394
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
8395
GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
8396
#endif
8397
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
8398
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
8399

    
8400
#undef GEN_LDF
8401
#undef GEN_LDUF
8402
#undef GEN_LDUXF
8403
#undef GEN_LDXF
8404
#undef GEN_LDFS
8405
#define GEN_LDF(name, ldop, opc, type)                                        \
8406
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8407
#define GEN_LDUF(name, ldop, opc, type)                                       \
8408
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8409
#define GEN_LDUXF(name, ldop, opc, type)                                      \
8410
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8411
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
8412
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8413
#define GEN_LDFS(name, ldop, op, type)                                        \
8414
GEN_LDF(name, ldop, op | 0x20, type)                                          \
8415
GEN_LDUF(name, ldop, op | 0x21, type)                                         \
8416
GEN_LDUXF(name, ldop, op | 0x01, type)                                        \
8417
GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
8418

    
8419
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
8420
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
8421

    
8422
#undef GEN_STF
8423
#undef GEN_STUF
8424
#undef GEN_STUXF
8425
#undef GEN_STXF
8426
#undef GEN_STFS
8427
#define GEN_STF(name, stop, opc, type)                                        \
8428
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8429
#define GEN_STUF(name, stop, opc, type)                                       \
8430
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8431
#define GEN_STUXF(name, stop, opc, type)                                      \
8432
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8433
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
8434
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8435
#define GEN_STFS(name, stop, op, type)                                        \
8436
GEN_STF(name, stop, op | 0x20, type)                                          \
8437
GEN_STUF(name, stop, op | 0x21, type)                                         \
8438
GEN_STUXF(name, stop, op | 0x01, type)                                        \
8439
GEN_STXF(name, stop, 0x17, op | 0x00, type)
8440

    
8441
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
8442
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
8443
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
8444

    
8445
#undef GEN_CRLOGIC
8446
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
8447
GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
8448
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
8449
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
8450
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
8451
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
8452
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
8453
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
8454
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
8455
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
8456

    
8457
#undef GEN_MAC_HANDLER
8458
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
8459
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
8460
GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
8461
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
8462
GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
8463
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
8464
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
8465
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
8466
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
8467
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
8468
GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
8469
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
8470
GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
8471
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
8472
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
8473
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
8474
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
8475
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
8476
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
8477
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
8478
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
8479
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
8480
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
8481
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
8482
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
8483
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
8484
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
8485
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
8486
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
8487
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
8488
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
8489
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
8490
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
8491
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
8492
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
8493
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
8494
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
8495
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
8496
GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
8497
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
8498
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
8499
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
8500
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
8501
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
8502

    
8503
#undef GEN_VR_LDX
8504
#undef GEN_VR_STX
8505
#undef GEN_VR_LVE
8506
#undef GEN_VR_STVE
8507
#define GEN_VR_LDX(name, opc2, opc3)                                          \
8508
GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8509
#define GEN_VR_STX(name, opc2, opc3)                                          \
8510
GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8511
#define GEN_VR_LVE(name, opc2, opc3)                                    \
8512
    GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8513
#define GEN_VR_STVE(name, opc2, opc3)                                   \
8514
    GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8515
GEN_VR_LDX(lvx, 0x07, 0x03),
8516
GEN_VR_LDX(lvxl, 0x07, 0x0B),
8517
GEN_VR_LVE(bx, 0x07, 0x00),
8518
GEN_VR_LVE(hx, 0x07, 0x01),
8519
GEN_VR_LVE(wx, 0x07, 0x02),
8520
GEN_VR_STX(svx, 0x07, 0x07),
8521
GEN_VR_STX(svxl, 0x07, 0x0F),
8522
GEN_VR_STVE(bx, 0x07, 0x04),
8523
GEN_VR_STVE(hx, 0x07, 0x05),
8524
GEN_VR_STVE(wx, 0x07, 0x06),
8525

    
8526
#undef GEN_VX_LOGICAL
8527
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
8528
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8529
GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
8530
GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
8531
GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
8532
GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
8533
GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),
8534

    
8535
#undef GEN_VXFORM
8536
#define GEN_VXFORM(name, opc2, opc3)                                    \
8537
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8538
GEN_VXFORM(vaddubm, 0, 0),
8539
GEN_VXFORM(vadduhm, 0, 1),
8540
GEN_VXFORM(vadduwm, 0, 2),
8541
GEN_VXFORM(vsububm, 0, 16),
8542
GEN_VXFORM(vsubuhm, 0, 17),
8543
GEN_VXFORM(vsubuwm, 0, 18),
8544
GEN_VXFORM(vmaxub, 1, 0),
8545
GEN_VXFORM(vmaxuh, 1, 1),
8546
GEN_VXFORM(vmaxuw, 1, 2),
8547
GEN_VXFORM(vmaxsb, 1, 4),
8548
GEN_VXFORM(vmaxsh, 1, 5),
8549
GEN_VXFORM(vmaxsw, 1, 6),
8550
GEN_VXFORM(vminub, 1, 8),
8551
GEN_VXFORM(vminuh, 1, 9),
8552
GEN_VXFORM(vminuw, 1, 10),
8553
GEN_VXFORM(vminsb, 1, 12),
8554
GEN_VXFORM(vminsh, 1, 13),
8555
GEN_VXFORM(vminsw, 1, 14),
8556
GEN_VXFORM(vavgub, 1, 16),
8557
GEN_VXFORM(vavguh, 1, 17),
8558
GEN_VXFORM(vavguw, 1, 18),
8559
GEN_VXFORM(vavgsb, 1, 20),
8560
GEN_VXFORM(vavgsh, 1, 21),
8561
GEN_VXFORM(vavgsw, 1, 22),
8562
GEN_VXFORM(vmrghb, 6, 0),
8563
GEN_VXFORM(vmrghh, 6, 1),
8564
GEN_VXFORM(vmrghw, 6, 2),
8565
GEN_VXFORM(vmrglb, 6, 4),
8566
GEN_VXFORM(vmrglh, 6, 5),
8567
GEN_VXFORM(vmrglw, 6, 6),
8568
GEN_VXFORM(vmuloub, 4, 0),
8569
GEN_VXFORM(vmulouh, 4, 1),
8570
GEN_VXFORM(vmulosb, 4, 4),
8571
GEN_VXFORM(vmulosh, 4, 5),
8572
GEN_VXFORM(vmuleub, 4, 8),
8573
GEN_VXFORM(vmuleuh, 4, 9),
8574
GEN_VXFORM(vmulesb, 4, 12),
8575
GEN_VXFORM(vmulesh, 4, 13),
8576
GEN_VXFORM(vslb, 2, 4),
8577
GEN_VXFORM(vslh, 2, 5),
8578
GEN_VXFORM(vslw, 2, 6),
8579
GEN_VXFORM(vsrb, 2, 8),
8580
GEN_VXFORM(vsrh, 2, 9),
8581
GEN_VXFORM(vsrw, 2, 10),
8582
GEN_VXFORM(vsrab, 2, 12),
8583
GEN_VXFORM(vsrah, 2, 13),
8584
GEN_VXFORM(vsraw, 2, 14),
8585
GEN_VXFORM(vslo, 6, 16),
8586
GEN_VXFORM(vsro, 6, 17),
8587
GEN_VXFORM(vaddcuw, 0, 6),
8588
GEN_VXFORM(vsubcuw, 0, 22),
8589
GEN_VXFORM(vaddubs, 0, 8),
8590
GEN_VXFORM(vadduhs, 0, 9),
8591
GEN_VXFORM(vadduws, 0, 10),
8592
GEN_VXFORM(vaddsbs, 0, 12),
8593
GEN_VXFORM(vaddshs, 0, 13),
8594
GEN_VXFORM(vaddsws, 0, 14),
8595
GEN_VXFORM(vsububs, 0, 24),
8596
GEN_VXFORM(vsubuhs, 0, 25),
8597
GEN_VXFORM(vsubuws, 0, 26),
8598
GEN_VXFORM(vsubsbs, 0, 28),
8599
GEN_VXFORM(vsubshs, 0, 29),
8600
GEN_VXFORM(vsubsws, 0, 30),
8601
GEN_VXFORM(vrlb, 2, 0),
8602
GEN_VXFORM(vrlh, 2, 1),
8603
GEN_VXFORM(vrlw, 2, 2),
8604
GEN_VXFORM(vsl, 2, 7),
8605
GEN_VXFORM(vsr, 2, 11),
8606
GEN_VXFORM(vpkuhum, 7, 0),
8607
GEN_VXFORM(vpkuwum, 7, 1),
8608
GEN_VXFORM(vpkuhus, 7, 2),
8609
GEN_VXFORM(vpkuwus, 7, 3),
8610
GEN_VXFORM(vpkshus, 7, 4),
8611
GEN_VXFORM(vpkswus, 7, 5),
8612
GEN_VXFORM(vpkshss, 7, 6),
8613
GEN_VXFORM(vpkswss, 7, 7),
8614
GEN_VXFORM(vpkpx, 7, 12),
8615
GEN_VXFORM(vsum4ubs, 4, 24),
8616
GEN_VXFORM(vsum4sbs, 4, 28),
8617
GEN_VXFORM(vsum4shs, 4, 25),
8618
GEN_VXFORM(vsum2sws, 4, 26),
8619
GEN_VXFORM(vsumsws, 4, 30),
8620
GEN_VXFORM(vaddfp, 5, 0),
8621
GEN_VXFORM(vsubfp, 5, 1),
8622
GEN_VXFORM(vmaxfp, 5, 16),
8623
GEN_VXFORM(vminfp, 5, 17),
8624

    
8625
#undef GEN_VXRFORM1
8626
#undef GEN_VXRFORM
8627
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
8628
    GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
8629
#define GEN_VXRFORM(name, opc2, opc3)                                \
8630
    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
8631
    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
8632
GEN_VXRFORM(vcmpequb, 3, 0)
8633
GEN_VXRFORM(vcmpequh, 3, 1)
8634
GEN_VXRFORM(vcmpequw, 3, 2)
8635
GEN_VXRFORM(vcmpgtsb, 3, 12)
8636
GEN_VXRFORM(vcmpgtsh, 3, 13)
8637
GEN_VXRFORM(vcmpgtsw, 3, 14)
8638
GEN_VXRFORM(vcmpgtub, 3, 8)
8639
GEN_VXRFORM(vcmpgtuh, 3, 9)
8640
GEN_VXRFORM(vcmpgtuw, 3, 10)
8641
GEN_VXRFORM(vcmpeqfp, 3, 3)
8642
GEN_VXRFORM(vcmpgefp, 3, 7)
8643
GEN_VXRFORM(vcmpgtfp, 3, 11)
8644
GEN_VXRFORM(vcmpbfp, 3, 15)
8645

    
8646
#undef GEN_VXFORM_SIMM
8647
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
8648
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8649
GEN_VXFORM_SIMM(vspltisb, 6, 12),
8650
GEN_VXFORM_SIMM(vspltish, 6, 13),
8651
GEN_VXFORM_SIMM(vspltisw, 6, 14),
8652

    
8653
#undef GEN_VXFORM_NOA
8654
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
8655
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
8656
GEN_VXFORM_NOA(vupkhsb, 7, 8),
8657
GEN_VXFORM_NOA(vupkhsh, 7, 9),
8658
GEN_VXFORM_NOA(vupklsb, 7, 10),
8659
GEN_VXFORM_NOA(vupklsh, 7, 11),
8660
GEN_VXFORM_NOA(vupkhpx, 7, 13),
8661
GEN_VXFORM_NOA(vupklpx, 7, 15),
8662
GEN_VXFORM_NOA(vrefp, 5, 4),
8663
GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
8664
GEN_VXFORM_NOA(vlogefp, 5, 7),
8665
GEN_VXFORM_NOA(vrfim, 5, 8),
8666
GEN_VXFORM_NOA(vrfin, 5, 9),
8667
GEN_VXFORM_NOA(vrfip, 5, 10),
8668
GEN_VXFORM_NOA(vrfiz, 5, 11),
8669

    
8670
#undef GEN_VXFORM_UIMM
8671
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
8672
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8673
GEN_VXFORM_UIMM(vspltb, 6, 8),
8674
GEN_VXFORM_UIMM(vsplth, 6, 9),
8675
GEN_VXFORM_UIMM(vspltw, 6, 10),
8676
GEN_VXFORM_UIMM(vcfux, 5, 12),
8677
GEN_VXFORM_UIMM(vcfsx, 5, 13),
8678
GEN_VXFORM_UIMM(vctuxs, 5, 14),
8679
GEN_VXFORM_UIMM(vctsxs, 5, 15),
8680

    
8681
#undef GEN_VAFORM_PAIRED
8682
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
8683
    GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
8684
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
8685
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
8686
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
8687
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
8688
GEN_VAFORM_PAIRED(vsel, vperm, 21),
8689
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
8690

    
8691
#undef GEN_SPE
8692
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
8693
GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)
8694
GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE),
8695
GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE),
8696
GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE),
8697
GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE),
8698
GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE),
8699
GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE),
8700
GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE),
8701
GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE),
8702
GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE),
8703
GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE),
8704
GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE),
8705
GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE),
8706
GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE),
8707
GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE),
8708
GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE),
8709
GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE),
8710
GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE),
8711
GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE),
8712
GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE),
8713
GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE),
8714
GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE),
8715
GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE),
8716
GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE),
8717
GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE),
8718
GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE),
8719

    
8720
GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE),
8721
GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE),
8722
GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE),
8723
GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE),
8724
GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE),
8725
GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE),
8726
GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8727
GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8728
GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8729
GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8730
GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8731
GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE),
8732
GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE),
8733
GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE),
8734

    
8735
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE),
8736
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE),
8737
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE),
8738
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE),
8739
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE),
8740
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE),
8741
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8742
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8743
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8744
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8745
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8746
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE),
8747
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE),
8748
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE),
8749

    
8750
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
8751
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8752
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
8753
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
8754
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
8755
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8756
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
8757
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
8758
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8759
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8760
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8761
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8762
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8763
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
8764
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
8765
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
8766

    
8767
#undef GEN_SPEOP_LDST
8768
#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
8769
GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)
8770
GEN_SPEOP_LDST(evldd, 0x00, 3),
8771
GEN_SPEOP_LDST(evldw, 0x01, 3),
8772
GEN_SPEOP_LDST(evldh, 0x02, 3),
8773
GEN_SPEOP_LDST(evlhhesplat, 0x04, 1),
8774
GEN_SPEOP_LDST(evlhhousplat, 0x06, 1),
8775
GEN_SPEOP_LDST(evlhhossplat, 0x07, 1),
8776
GEN_SPEOP_LDST(evlwhe, 0x08, 2),
8777
GEN_SPEOP_LDST(evlwhou, 0x0A, 2),
8778
GEN_SPEOP_LDST(evlwhos, 0x0B, 2),
8779
GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2),
8780
GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2),
8781

    
8782
GEN_SPEOP_LDST(evstdd, 0x10, 3),
8783
GEN_SPEOP_LDST(evstdw, 0x11, 3),
8784
GEN_SPEOP_LDST(evstdh, 0x12, 3),
8785
GEN_SPEOP_LDST(evstwhe, 0x18, 2),
8786
GEN_SPEOP_LDST(evstwho, 0x1A, 2),
8787
GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
8788
GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
8789
};
8790

    
8791
#include "translate_init.c"
8792
#include "helper_regs.h"
8793

    
8794
/*****************************************************************************/
8795
/* Misc PowerPC helpers */
8796
void cpu_dump_state (CPUState *env, FILE *f,
8797
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8798
                     int flags)
8799
{
8800
#define RGPL  4
8801
#define RFPL  4
8802

    
8803
    int i;
8804

    
8805
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
8806
                env->nip, env->lr, env->ctr, env->xer);
8807
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
8808
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
8809
#if !defined(NO_TIMER_DUMP)
8810
    cpu_fprintf(f, "TB %08x %08x "
8811
#if !defined(CONFIG_USER_ONLY)
8812
                "DECR %08x"
8813
#endif
8814
                "\n",
8815
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
8816
#if !defined(CONFIG_USER_ONLY)
8817
                , cpu_ppc_load_decr(env)
8818
#endif
8819
                );
8820
#endif
8821
    for (i = 0; i < 32; i++) {
8822
        if ((i & (RGPL - 1)) == 0)
8823
            cpu_fprintf(f, "GPR%02d", i);
8824
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
8825
        if ((i & (RGPL - 1)) == (RGPL - 1))
8826
            cpu_fprintf(f, "\n");
8827
    }
8828
    cpu_fprintf(f, "CR ");
8829
    for (i = 0; i < 8; i++)
8830
        cpu_fprintf(f, "%01x", env->crf[i]);
8831
    cpu_fprintf(f, "  [");
8832
    for (i = 0; i < 8; i++) {
8833
        char a = '-';
8834
        if (env->crf[i] & 0x08)
8835
            a = 'L';
8836
        else if (env->crf[i] & 0x04)
8837
            a = 'G';
8838
        else if (env->crf[i] & 0x02)
8839
            a = 'E';
8840
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
8841
    }
8842
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve_addr);
8843
    for (i = 0; i < 32; i++) {
8844
        if ((i & (RFPL - 1)) == 0)
8845
            cpu_fprintf(f, "FPR%02d", i);
8846
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
8847
        if ((i & (RFPL - 1)) == (RFPL - 1))
8848
            cpu_fprintf(f, "\n");
8849
    }
8850
    cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
8851
#if !defined(CONFIG_USER_ONLY)
8852
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
8853
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
8854
#endif
8855

    
8856
#undef RGPL
8857
#undef RFPL
8858
}
8859

    
8860
void cpu_dump_statistics (CPUState *env, FILE*f,
8861
                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8862
                          int flags)
8863
{
8864
#if defined(DO_PPC_STATISTICS)
8865
    opc_handler_t **t1, **t2, **t3, *handler;
8866
    int op1, op2, op3;
8867

    
8868
    t1 = env->opcodes;
8869
    for (op1 = 0; op1 < 64; op1++) {
8870
        handler = t1[op1];
8871
        if (is_indirect_opcode(handler)) {
8872
            t2 = ind_table(handler);
8873
            for (op2 = 0; op2 < 32; op2++) {
8874
                handler = t2[op2];
8875
                if (is_indirect_opcode(handler)) {
8876
                    t3 = ind_table(handler);
8877
                    for (op3 = 0; op3 < 32; op3++) {
8878
                        handler = t3[op3];
8879
                        if (handler->count == 0)
8880
                            continue;
8881
                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
8882
                                    "%016llx %lld\n",
8883
                                    op1, op2, op3, op1, (op3 << 5) | op2,
8884
                                    handler->oname,
8885
                                    handler->count, handler->count);
8886
                    }
8887
                } else {
8888
                    if (handler->count == 0)
8889
                        continue;
8890
                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
8891
                                "%016llx %lld\n",
8892
                                op1, op2, op1, op2, handler->oname,
8893
                                handler->count, handler->count);
8894
                }
8895
            }
8896
        } else {
8897
            if (handler->count == 0)
8898
                continue;
8899
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016llx %lld\n",
8900
                        op1, op1, handler->oname,
8901
                        handler->count, handler->count);
8902
        }
8903
    }
8904
#endif
8905
}
8906

    
8907
/*****************************************************************************/
8908
static always_inline void gen_intermediate_code_internal (CPUState *env,
8909
                                                          TranslationBlock *tb,
8910
                                                          int search_pc)
8911
{
8912
    DisasContext ctx, *ctxp = &ctx;
8913
    opc_handler_t **table, *handler;
8914
    target_ulong pc_start;
8915
    uint16_t *gen_opc_end;
8916
    CPUBreakpoint *bp;
8917
    int j, lj = -1;
8918
    int num_insns;
8919
    int max_insns;
8920

    
8921
    pc_start = tb->pc;
8922
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8923
    ctx.nip = pc_start;
8924
    ctx.tb = tb;
8925
    ctx.exception = POWERPC_EXCP_NONE;
8926
    ctx.spr_cb = env->spr_cb;
8927
    ctx.mem_idx = env->mmu_idx;
8928
    ctx.access_type = -1;
8929
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
8930
#if defined(TARGET_PPC64)
8931
    ctx.sf_mode = msr_sf;
8932
#endif
8933
    ctx.fpu_enabled = msr_fp;
8934
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
8935
        ctx.spe_enabled = msr_spe;
8936
    else
8937
        ctx.spe_enabled = 0;
8938
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
8939
        ctx.altivec_enabled = msr_vr;
8940
    else
8941
        ctx.altivec_enabled = 0;
8942
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8943
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
8944
    else
8945
        ctx.singlestep_enabled = 0;
8946
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8947
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
8948
    if (unlikely(env->singlestep_enabled))
8949
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
8950
#if defined (DO_SINGLE_STEP) && 0
8951
    /* Single step trace mode */
8952
    msr_se = 1;
8953
#endif
8954
    num_insns = 0;
8955
    max_insns = tb->cflags & CF_COUNT_MASK;
8956
    if (max_insns == 0)
8957
        max_insns = CF_COUNT_MASK;
8958

    
8959
    gen_icount_start();
8960
    /* Set env in case of segfault during code fetch */
8961
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
8962
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8963
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8964
                if (bp->pc == ctx.nip) {
8965
                    gen_debug_exception(ctxp);
8966
                    break;
8967
                }
8968
            }
8969
        }
8970
        if (unlikely(search_pc)) {
8971
            j = gen_opc_ptr - gen_opc_buf;
8972
            if (lj < j) {
8973
                lj++;
8974
                while (lj < j)
8975
                    gen_opc_instr_start[lj++] = 0;
8976
            }
8977
            gen_opc_pc[lj] = ctx.nip;
8978
            gen_opc_instr_start[lj] = 1;
8979
            gen_opc_icount[lj] = num_insns;
8980
        }
8981
        LOG_DISAS("----------------\n");
8982
        LOG_DISAS("nip=" ADDRX " super=%d ir=%d\n",
8983
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
8984
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8985
            gen_io_start();
8986
        if (unlikely(ctx.le_mode)) {
8987
            ctx.opcode = bswap32(ldl_code(ctx.nip));
8988
        } else {
8989
            ctx.opcode = ldl_code(ctx.nip);
8990
        }
8991
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
8992
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
8993
                    opc3(ctx.opcode), little_endian ? "little" : "big");
8994
        ctx.nip += 4;
8995
        table = env->opcodes;
8996
        num_insns++;
8997
        handler = table[opc1(ctx.opcode)];
8998
        if (is_indirect_opcode(handler)) {
8999
            table = ind_table(handler);
9000
            handler = table[opc2(ctx.opcode)];
9001
            if (is_indirect_opcode(handler)) {
9002
                table = ind_table(handler);
9003
                handler = table[opc3(ctx.opcode)];
9004
            }
9005
        }
9006
        /* Is opcode *REALLY* valid ? */
9007
        if (unlikely(handler->handler == &gen_invalid)) {
9008
            if (qemu_log_enabled()) {
9009
                qemu_log("invalid/unsupported opcode: "
9010
                          "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
9011
                          opc1(ctx.opcode), opc2(ctx.opcode),
9012
                          opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
9013
            } else {
9014
                printf("invalid/unsupported opcode: "
9015
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
9016
                       opc1(ctx.opcode), opc2(ctx.opcode),
9017
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
9018
            }
9019
        } else {
9020
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
9021
                if (qemu_log_enabled()) {
9022
                    qemu_log("invalid bits: %08x for opcode: "
9023
                              "%02x - %02x - %02x (%08x) " ADDRX "\n",
9024
                              ctx.opcode & handler->inval, opc1(ctx.opcode),
9025
                              opc2(ctx.opcode), opc3(ctx.opcode),
9026
                              ctx.opcode, ctx.nip - 4);
9027
                } else {
9028
                    printf("invalid bits: %08x for opcode: "
9029
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
9030
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
9031
                           opc2(ctx.opcode), opc3(ctx.opcode),
9032
                           ctx.opcode, ctx.nip - 4);
9033
                }
9034
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
9035
                break;
9036
            }
9037
        }
9038
        (*(handler->handler))(&ctx);
9039
#if defined(DO_PPC_STATISTICS)
9040
        handler->count++;
9041
#endif
9042
        /* Check trace mode exceptions */
9043
        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
9044
                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
9045
                     ctx.exception != POWERPC_SYSCALL &&
9046
                     ctx.exception != POWERPC_EXCP_TRAP &&
9047
                     ctx.exception != POWERPC_EXCP_BRANCH)) {
9048
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
9049
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
9050
                            (env->singlestep_enabled) ||
9051
                            singlestep ||
9052
                            num_insns >= max_insns)) {
9053
            /* if we reach a page boundary or are single stepping, stop
9054
             * generation
9055
             */
9056
            break;
9057
        }
9058
    }
9059
    if (tb->cflags & CF_LAST_IO)
9060
        gen_io_end();
9061
    if (ctx.exception == POWERPC_EXCP_NONE) {
9062
        gen_goto_tb(&ctx, 0, ctx.nip);
9063
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
9064
        if (unlikely(env->singlestep_enabled)) {
9065
            gen_debug_exception(ctxp);
9066
        }
9067
        /* Generate the return instruction */
9068
        tcg_gen_exit_tb(0);
9069
    }
9070
    gen_icount_end(tb, num_insns);
9071
    *gen_opc_ptr = INDEX_op_end;
9072
    if (unlikely(search_pc)) {
9073
        j = gen_opc_ptr - gen_opc_buf;
9074
        lj++;
9075
        while (lj <= j)
9076
            gen_opc_instr_start[lj++] = 0;
9077
    } else {
9078
        tb->size = ctx.nip - pc_start;
9079
        tb->icount = num_insns;
9080
    }
9081
#if defined(DEBUG_DISAS)
9082
    qemu_log_mask(CPU_LOG_TB_CPU, "---------------- excp: %04x\n", ctx.exception);
9083
    log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
9084
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9085
        int flags;
9086
        flags = env->bfd_mach;
9087
        flags |= ctx.le_mode << 16;
9088
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
9089
        log_target_disas(pc_start, ctx.nip - pc_start, flags);
9090
        qemu_log("\n");
9091
    }
9092
#endif
9093
}
9094

    
9095
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
9096
{
9097
    gen_intermediate_code_internal(env, tb, 0);
9098
}
9099

    
9100
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
9101
{
9102
    gen_intermediate_code_internal(env, tb, 1);
9103
}
9104

    
9105
void gen_pc_load(CPUState *env, TranslationBlock *tb,
9106
                unsigned long searched_pc, int pc_pos, void *puc)
9107
{
9108
    env->nip = gen_opc_pc[pc_pos];
9109
}