Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ 604457d7

History | View | Annotate | Download (307.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, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25

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

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

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

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

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

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

    
79
#include "gen-icount.h"
80

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

    
87
    if (done_init)
88
        return;
89

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

    
92
    p = cpu_reg_names;
93

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

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

    
113
        sprintf(p, "fp%d", i);
114
        cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
115
                                            offsetof(CPUState, fpr[i]), p);
116
        p += (i < 10) ? 4 : 5;
117

    
118
        sprintf(p, "avr%dH", i);
119
#ifdef WORDS_BIGENDIAN
120
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
121
                                             offsetof(CPUState, avr[i].u64[0]), p);
122
#else
123
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
124
                                             offsetof(CPUState, avr[i].u64[1]), p);
125
#endif
126
        p += (i < 10) ? 6 : 7;
127

    
128
        sprintf(p, "avr%dL", i);
129
#ifdef WORDS_BIGENDIAN
130
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
131
                                             offsetof(CPUState, avr[i].u64[1]), p);
132
#else
133
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
134
                                             offsetof(CPUState, avr[i].u64[0]), p);
135
#endif
136
        p += (i < 10) ? 6 : 7;
137
    }
138

    
139
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
140
                                 offsetof(CPUState, nip), "nip");
141

    
142
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
143
                                 offsetof(CPUState, msr), "msr");
144

    
145
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
146
                                 offsetof(CPUState, ctr), "ctr");
147

    
148
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
149
                                offsetof(CPUState, lr), "lr");
150

    
151
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
152
                                 offsetof(CPUState, xer), "xer");
153

    
154
    cpu_reserve = tcg_global_mem_new(TCG_AREG0,
155
                                     offsetof(CPUState, reserve), "reserve");
156

    
157
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
158
                                       offsetof(CPUState, fpscr), "fpscr");
159

    
160
    cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
161
                                             offsetof(CPUState, access_type), "access_type");
162

    
163
    /* register helpers */
164
#define GEN_HELPER 2
165
#include "helper.h"
166

    
167
    done_init = 1;
168
}
169

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

    
191
struct opc_handler_t {
192
    /* invalid bits */
193
    uint32_t inval;
194
    /* instruction type */
195
    uint64_t type;
196
    /* handler */
197
    void (*handler)(DisasContext *ctx);
198
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
199
    const char *oname;
200
#endif
201
#if defined(DO_PPC_STATISTICS)
202
    uint64_t count;
203
#endif
204
};
205

    
206
static always_inline void gen_reset_fpstatus (void)
207
{
208
#ifdef CONFIG_SOFTFLOAT
209
    gen_helper_reset_fpstatus();
210
#endif
211
}
212

    
213
static always_inline void gen_compute_fprf (TCGv_i64 arg, int set_fprf, int set_rc)
214
{
215
    TCGv_i32 t0 = tcg_temp_new_i32();
216

    
217
    if (set_fprf != 0) {
218
        /* This case might be optimized later */
219
        tcg_gen_movi_i32(t0, 1);
220
        gen_helper_compute_fprf(t0, arg, t0);
221
        if (unlikely(set_rc)) {
222
            tcg_gen_mov_i32(cpu_crf[1], t0);
223
        }
224
        gen_helper_float_check_status();
225
    } else if (unlikely(set_rc)) {
226
        /* We always need to compute fpcc */
227
        tcg_gen_movi_i32(t0, 0);
228
        gen_helper_compute_fprf(t0, arg, t0);
229
        tcg_gen_mov_i32(cpu_crf[1], t0);
230
    }
231

    
232
    tcg_temp_free_i32(t0);
233
}
234

    
235
static always_inline void gen_set_access_type (DisasContext *ctx, int access_type)
236
{
237
    if (ctx->access_type != access_type) {
238
        tcg_gen_movi_i32(cpu_access_type, access_type);
239
        ctx->access_type = access_type;
240
    }
241
}
242

    
243
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
244
{
245
#if defined(TARGET_PPC64)
246
    if (ctx->sf_mode)
247
        tcg_gen_movi_tl(cpu_nip, nip);
248
    else
249
#endif
250
        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
251
}
252

    
253
static always_inline void gen_exception_err (DisasContext *ctx, uint32_t excp, uint32_t error)
254
{
255
    TCGv_i32 t0, t1;
256
    if (ctx->exception == POWERPC_EXCP_NONE) {
257
        gen_update_nip(ctx, ctx->nip);
258
    }
259
    t0 = tcg_const_i32(excp);
260
    t1 = tcg_const_i32(error);
261
    gen_helper_raise_exception_err(t0, t1);
262
    tcg_temp_free_i32(t0);
263
    tcg_temp_free_i32(t1);
264
    ctx->exception = (excp);
265
}
266

    
267
static always_inline void gen_exception (DisasContext *ctx, uint32_t excp)
268
{
269
    TCGv_i32 t0;
270
    if (ctx->exception == POWERPC_EXCP_NONE) {
271
        gen_update_nip(ctx, ctx->nip);
272
    }
273
    t0 = tcg_const_i32(excp);
274
    gen_helper_raise_exception(t0);
275
    tcg_temp_free_i32(t0);
276
    ctx->exception = (excp);
277
}
278

    
279
static always_inline void gen_debug_exception (DisasContext *ctx)
280
{
281
    TCGv_i32 t0;
282

    
283
    if (ctx->exception != POWERPC_EXCP_BRANCH)
284
        gen_update_nip(ctx, ctx->nip);
285
    t0 = tcg_const_i32(EXCP_DEBUG);
286
    gen_helper_raise_exception(t0);
287
    tcg_temp_free_i32(t0);
288
}
289

    
290
static always_inline void gen_inval_exception (DisasContext *ctx, uint32_t error)
291
{
292
    gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
293
}
294

    
295
/* Stop translation */
296
static always_inline void gen_stop_exception (DisasContext *ctx)
297
{
298
    gen_update_nip(ctx, ctx->nip);
299
    ctx->exception = POWERPC_EXCP_STOP;
300
}
301

    
302
/* No need to update nip here, as execution flow will change */
303
static always_inline void gen_sync_exception (DisasContext *ctx)
304
{
305
    ctx->exception = POWERPC_EXCP_SYNC;
306
}
307

    
308
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
309
static void gen_##name (DisasContext *ctx);                                   \
310
GEN_OPCODE(name, opc1, opc2, opc3, inval, type);                              \
311
static void gen_##name (DisasContext *ctx)
312

    
313
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
314
static void gen_##name (DisasContext *ctx);                                   \
315
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type);                       \
316
static void gen_##name (DisasContext *ctx)
317

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

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

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

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

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

    
398
EXTRACT_HELPER(CRM, 12, 8);
399
EXTRACT_HELPER(FM, 17, 8);
400
EXTRACT_HELPER(SR, 16, 4);
401
EXTRACT_HELPER(FPIMM, 12, 4);
402

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

    
412
static always_inline uint32_t BD (uint32_t opcode)
413
{
414
    return (opcode >> 0) & 0xFFFC;
415
}
416

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

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

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

    
449
    return ret;
450
}
451

    
452
/*****************************************************************************/
453
/* PowerPC Instructions types definitions                                    */
454
enum {
455
    PPC_NONE           = 0x0000000000000000ULL,
456
    /* PowerPC base instructions set                                         */
457
    PPC_INSNS_BASE     = 0x0000000000000001ULL,
458
    /*   integer operations instructions                                     */
459
#define PPC_INTEGER PPC_INSNS_BASE
460
    /*   flow control instructions                                           */
461
#define PPC_FLOW    PPC_INSNS_BASE
462
    /*   virtual memory instructions                                         */
463
#define PPC_MEM     PPC_INSNS_BASE
464
    /*   ld/st with reservation instructions                                 */
465
#define PPC_RES     PPC_INSNS_BASE
466
    /*   spr/msr access instructions                                         */
467
#define PPC_MISC    PPC_INSNS_BASE
468
    /* Deprecated instruction sets                                           */
469
    /*   Original POWER instruction set                                      */
470
    PPC_POWER          = 0x0000000000000002ULL,
471
    /*   POWER2 instruction set extension                                    */
472
    PPC_POWER2         = 0x0000000000000004ULL,
473
    /*   Power RTC support                                                   */
474
    PPC_POWER_RTC      = 0x0000000000000008ULL,
475
    /*   Power-to-PowerPC bridge (601)                                       */
476
    PPC_POWER_BR       = 0x0000000000000010ULL,
477
    /* 64 bits PowerPC instruction set                                       */
478
    PPC_64B            = 0x0000000000000020ULL,
479
    /*   New 64 bits extensions (PowerPC 2.0x)                               */
480
    PPC_64BX           = 0x0000000000000040ULL,
481
    /*   64 bits hypervisor extensions                                       */
482
    PPC_64H            = 0x0000000000000080ULL,
483
    /*   New wait instruction (PowerPC 2.0x)                                 */
484
    PPC_WAIT           = 0x0000000000000100ULL,
485
    /*   Time base mftb instruction                                          */
486
    PPC_MFTB           = 0x0000000000000200ULL,
487

    
488
    /* Fixed-point unit extensions                                           */
489
    /*   PowerPC 602 specific                                                */
490
    PPC_602_SPEC       = 0x0000000000000400ULL,
491
    /*   isel instruction                                                    */
492
    PPC_ISEL           = 0x0000000000000800ULL,
493
    /*   popcntb instruction                                                 */
494
    PPC_POPCNTB        = 0x0000000000001000ULL,
495
    /*   string load / store                                                 */
496
    PPC_STRING         = 0x0000000000002000ULL,
497

    
498
    /* Floating-point unit extensions                                        */
499
    /*   Optional floating point instructions                                */
500
    PPC_FLOAT          = 0x0000000000010000ULL,
501
    /* New floating-point extensions (PowerPC 2.0x)                          */
502
    PPC_FLOAT_EXT      = 0x0000000000020000ULL,
503
    PPC_FLOAT_FSQRT    = 0x0000000000040000ULL,
504
    PPC_FLOAT_FRES     = 0x0000000000080000ULL,
505
    PPC_FLOAT_FRSQRTE  = 0x0000000000100000ULL,
506
    PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
507
    PPC_FLOAT_FSEL     = 0x0000000000400000ULL,
508
    PPC_FLOAT_STFIWX   = 0x0000000000800000ULL,
509

    
510
    /* Vector/SIMD extensions                                                */
511
    /*   Altivec support                                                     */
512
    PPC_ALTIVEC        = 0x0000000001000000ULL,
513
    /*   PowerPC 2.03 SPE extension                                          */
514
    PPC_SPE            = 0x0000000002000000ULL,
515
    /*   PowerPC 2.03 SPE single-precision floating-point extension          */
516
    PPC_SPE_SINGLE     = 0x0000000004000000ULL,
517
    /*   PowerPC 2.03 SPE double-precision floating-point extension          */
518
    PPC_SPE_DOUBLE     = 0x0000000008000000ULL,
519

    
520
    /* Optional memory control instructions                                  */
521
    PPC_MEM_TLBIA      = 0x0000000010000000ULL,
522
    PPC_MEM_TLBIE      = 0x0000000020000000ULL,
523
    PPC_MEM_TLBSYNC    = 0x0000000040000000ULL,
524
    /*   sync instruction                                                    */
525
    PPC_MEM_SYNC       = 0x0000000080000000ULL,
526
    /*   eieio instruction                                                   */
527
    PPC_MEM_EIEIO      = 0x0000000100000000ULL,
528

    
529
    /* Cache control instructions                                            */
530
    PPC_CACHE          = 0x0000000200000000ULL,
531
    /*   icbi instruction                                                    */
532
    PPC_CACHE_ICBI     = 0x0000000400000000ULL,
533
    /*   dcbz instruction with fixed cache line size                         */
534
    PPC_CACHE_DCBZ     = 0x0000000800000000ULL,
535
    /*   dcbz instruction with tunable cache line size                       */
536
    PPC_CACHE_DCBZT    = 0x0000001000000000ULL,
537
    /*   dcba instruction                                                    */
538
    PPC_CACHE_DCBA     = 0x0000002000000000ULL,
539
    /*   Freescale cache locking instructions                                */
540
    PPC_CACHE_LOCK     = 0x0000004000000000ULL,
541

    
542
    /* MMU related extensions                                                */
543
    /*   external control instructions                                       */
544
    PPC_EXTERN         = 0x0000010000000000ULL,
545
    /*   segment register access instructions                                */
546
    PPC_SEGMENT        = 0x0000020000000000ULL,
547
    /*   PowerPC 6xx TLB management instructions                             */
548
    PPC_6xx_TLB        = 0x0000040000000000ULL,
549
    /* PowerPC 74xx TLB management instructions                              */
550
    PPC_74xx_TLB       = 0x0000080000000000ULL,
551
    /*   PowerPC 40x TLB management instructions                             */
552
    PPC_40x_TLB        = 0x0000100000000000ULL,
553
    /*   segment register access instructions for PowerPC 64 "bridge"        */
554
    PPC_SEGMENT_64B    = 0x0000200000000000ULL,
555
    /*   SLB management                                                      */
556
    PPC_SLBI           = 0x0000400000000000ULL,
557

    
558
    /* Embedded PowerPC dedicated instructions                               */
559
    PPC_WRTEE          = 0x0001000000000000ULL,
560
    /* PowerPC 40x exception model                                           */
561
    PPC_40x_EXCP       = 0x0002000000000000ULL,
562
    /* PowerPC 405 Mac instructions                                          */
563
    PPC_405_MAC        = 0x0004000000000000ULL,
564
    /* PowerPC 440 specific instructions                                     */
565
    PPC_440_SPEC       = 0x0008000000000000ULL,
566
    /* BookE (embedded) PowerPC specification                                */
567
    PPC_BOOKE          = 0x0010000000000000ULL,
568
    /* mfapidi instruction                                                   */
569
    PPC_MFAPIDI        = 0x0020000000000000ULL,
570
    /* tlbiva instruction                                                    */
571
    PPC_TLBIVA         = 0x0040000000000000ULL,
572
    /* tlbivax instruction                                                   */
573
    PPC_TLBIVAX        = 0x0080000000000000ULL,
574
    /* PowerPC 4xx dedicated instructions                                    */
575
    PPC_4xx_COMMON     = 0x0100000000000000ULL,
576
    /* PowerPC 40x ibct instructions                                         */
577
    PPC_40x_ICBT       = 0x0200000000000000ULL,
578
    /* rfmci is not implemented in all BookE PowerPC                         */
579
    PPC_RFMCI          = 0x0400000000000000ULL,
580
    /* rfdi instruction                                                      */
581
    PPC_RFDI           = 0x0800000000000000ULL,
582
    /* DCR accesses                                                          */
583
    PPC_DCR            = 0x1000000000000000ULL,
584
    /* DCR extended accesse                                                  */
585
    PPC_DCRX           = 0x2000000000000000ULL,
586
    /* user-mode DCR access, implemented in PowerPC 460                      */
587
    PPC_DCRUX          = 0x4000000000000000ULL,
588
};
589

    
590
/*****************************************************************************/
591
/* PowerPC instructions table                                                */
592
#if HOST_LONG_BITS == 64
593
#define OPC_ALIGN 8
594
#else
595
#define OPC_ALIGN 4
596
#endif
597
#if defined(__APPLE__)
598
#define OPCODES_SECTION                                                       \
599
    __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
600
#else
601
#define OPCODES_SECTION                                                       \
602
    __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
603
#endif
604

    
605
#if defined(DO_PPC_STATISTICS)
606
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
607
extern opcode_t opc_##name;                                                   \
608
OPCODES_SECTION opcode_t opc_##name = {                                       \
609
    .opc1 = op1,                                                              \
610
    .opc2 = op2,                                                              \
611
    .opc3 = op3,                                                              \
612
    .pad  = { 0, },                                                           \
613
    .handler = {                                                              \
614
        .inval   = invl,                                                      \
615
        .type = _typ,                                                         \
616
        .handler = &gen_##name,                                               \
617
        .oname = stringify(name),                                             \
618
    },                                                                        \
619
    .oname = stringify(name),                                                 \
620
}
621
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
622
OPCODES_SECTION opcode_t opc_##name = {                                       \
623
    .opc1 = op1,                                                              \
624
    .opc2 = op2,                                                              \
625
    .opc3 = op3,                                                              \
626
    .pad  = { 0, },                                                           \
627
    .handler = {                                                              \
628
        .inval   = invl,                                                      \
629
        .type = _typ,                                                         \
630
        .handler = &gen_##name,                                               \
631
        .oname = onam,                                                        \
632
    },                                                                        \
633
    .oname = onam,                                                            \
634
}
635
#else
636
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
637
extern opcode_t opc_##name;                                                   \
638
OPCODES_SECTION opcode_t opc_##name = {                                       \
639
    .opc1 = op1,                                                              \
640
    .opc2 = op2,                                                              \
641
    .opc3 = op3,                                                              \
642
    .pad  = { 0, },                                                           \
643
    .handler = {                                                              \
644
        .inval   = invl,                                                      \
645
        .type = _typ,                                                         \
646
        .handler = &gen_##name,                                               \
647
    },                                                                        \
648
    .oname = stringify(name),                                                 \
649
}
650
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
651
extern opcode_t opc_##name;                                                   \
652
OPCODES_SECTION opcode_t opc_##name = {                                       \
653
    .opc1 = op1,                                                              \
654
    .opc2 = op2,                                                              \
655
    .opc3 = op3,                                                              \
656
    .pad  = { 0, },                                                           \
657
    .handler = {                                                              \
658
        .inval   = invl,                                                      \
659
        .type = _typ,                                                         \
660
        .handler = &gen_##name,                                               \
661
    },                                                                        \
662
    .oname = onam,                                                            \
663
}
664
#endif
665

    
666
#define GEN_OPCODE_MARK(name)                                                 \
667
extern opcode_t opc_##name;                                                   \
668
OPCODES_SECTION opcode_t opc_##name = {                                       \
669
    .opc1 = 0xFF,                                                             \
670
    .opc2 = 0xFF,                                                             \
671
    .opc3 = 0xFF,                                                             \
672
    .pad  = { 0, },                                                           \
673
    .handler = {                                                              \
674
        .inval   = 0x00000000,                                                \
675
        .type = 0x00,                                                         \
676
        .handler = NULL,                                                      \
677
    },                                                                        \
678
    .oname = stringify(name),                                                 \
679
}
680

    
681
/* SPR load/store helpers */
682
static always_inline void gen_load_spr(TCGv t, int reg)
683
{
684
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
685
}
686

    
687
static always_inline void gen_store_spr(int reg, TCGv t)
688
{
689
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
690
}
691

    
692
/* Start opcode list */
693
GEN_OPCODE_MARK(start);
694

    
695
/* Invalid instruction */
696
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
697
{
698
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
699
}
700

    
701
static opc_handler_t invalid_handler = {
702
    .inval   = 0xFFFFFFFF,
703
    .type    = PPC_NONE,
704
    .handler = gen_invalid,
705
};
706

    
707
/***                           Integer comparison                          ***/
708

    
709
static always_inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
710
{
711
    int l1, l2, l3;
712

    
713
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
714
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
715
    tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);
716

    
717
    l1 = gen_new_label();
718
    l2 = gen_new_label();
719
    l3 = gen_new_label();
720
    if (s) {
721
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
722
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
723
    } else {
724
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
725
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
726
    }
727
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
728
    tcg_gen_br(l3);
729
    gen_set_label(l1);
730
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
731
    tcg_gen_br(l3);
732
    gen_set_label(l2);
733
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
734
    gen_set_label(l3);
735
}
736

    
737
static always_inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
738
{
739
    TCGv t0 = tcg_const_local_tl(arg1);
740
    gen_op_cmp(arg0, t0, s, crf);
741
    tcg_temp_free(t0);
742
}
743

    
744
#if defined(TARGET_PPC64)
745
static always_inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
746
{
747
    TCGv t0, t1;
748
    t0 = tcg_temp_local_new();
749
    t1 = tcg_temp_local_new();
750
    if (s) {
751
        tcg_gen_ext32s_tl(t0, arg0);
752
        tcg_gen_ext32s_tl(t1, arg1);
753
    } else {
754
        tcg_gen_ext32u_tl(t0, arg0);
755
        tcg_gen_ext32u_tl(t1, arg1);
756
    }
757
    gen_op_cmp(t0, t1, s, crf);
758
    tcg_temp_free(t1);
759
    tcg_temp_free(t0);
760
}
761

    
762
static always_inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
763
{
764
    TCGv t0 = tcg_const_local_tl(arg1);
765
    gen_op_cmp32(arg0, t0, s, crf);
766
    tcg_temp_free(t0);
767
}
768
#endif
769

    
770
static always_inline void gen_set_Rc0 (DisasContext *ctx, TCGv reg)
771
{
772
#if defined(TARGET_PPC64)
773
    if (!(ctx->sf_mode))
774
        gen_op_cmpi32(reg, 0, 1, 0);
775
    else
776
#endif
777
        gen_op_cmpi(reg, 0, 1, 0);
778
}
779

    
780
/* cmp */
781
GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER)
782
{
783
#if defined(TARGET_PPC64)
784
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
785
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
786
                     1, crfD(ctx->opcode));
787
    else
788
#endif
789
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
790
                   1, crfD(ctx->opcode));
791
}
792

    
793
/* cmpi */
794
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
795
{
796
#if defined(TARGET_PPC64)
797
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
798
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
799
                      1, crfD(ctx->opcode));
800
    else
801
#endif
802
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
803
                    1, crfD(ctx->opcode));
804
}
805

    
806
/* cmpl */
807
GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER)
808
{
809
#if defined(TARGET_PPC64)
810
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
811
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
812
                     0, crfD(ctx->opcode));
813
    else
814
#endif
815
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
816
                   0, crfD(ctx->opcode));
817
}
818

    
819
/* cmpli */
820
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
821
{
822
#if defined(TARGET_PPC64)
823
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
824
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
825
                      0, crfD(ctx->opcode));
826
    else
827
#endif
828
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
829
                    0, crfD(ctx->opcode));
830
}
831

    
832
/* isel (PowerPC 2.03 specification) */
833
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
834
{
835
    int l1, l2;
836
    uint32_t bi = rC(ctx->opcode);
837
    uint32_t mask;
838
    TCGv_i32 t0;
839

    
840
    l1 = gen_new_label();
841
    l2 = gen_new_label();
842

    
843
    mask = 1 << (3 - (bi & 0x03));
844
    t0 = tcg_temp_new_i32();
845
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
846
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
847
    if (rA(ctx->opcode) == 0)
848
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
849
    else
850
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
851
    tcg_gen_br(l2);
852
    gen_set_label(l1);
853
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
854
    gen_set_label(l2);
855
    tcg_temp_free_i32(t0);
856
}
857

    
858
/***                           Integer arithmetic                          ***/
859

    
860
static always_inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, TCGv arg1, TCGv arg2, int sub)
861
{
862
    int l1;
863
    TCGv t0;
864

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

    
892
static always_inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, TCGv arg2, int sub)
893
{
894
    int l1 = gen_new_label();
895

    
896
#if defined(TARGET_PPC64)
897
    if (!(ctx->sf_mode)) {
898
        TCGv t0, t1;
899
        t0 = tcg_temp_new();
900
        t1 = tcg_temp_new();
901

    
902
        tcg_gen_ext32u_tl(t0, arg1);
903
        tcg_gen_ext32u_tl(t1, arg2);
904
        if (sub) {
905
            tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
906
        } else {
907
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
908
        }
909
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
910
        gen_set_label(l1);
911
        tcg_temp_free(t0);
912
        tcg_temp_free(t1);
913
    } else
914
#endif
915
    {
916
        if (sub) {
917
            tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
918
        } else {
919
            tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
920
        }
921
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
922
        gen_set_label(l1);
923
    }
924
}
925

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

    
932
    if ((!compute_ca && !compute_ov) ||
933
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
934
        t0 = ret;
935
    } else {
936
        t0 = tcg_temp_local_new();
937
    }
938

    
939
    if (add_ca) {
940
        t1 = tcg_temp_local_new();
941
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
942
        tcg_gen_shri_tl(t1, t1, XER_CA);
943
    }
944

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

    
956
    tcg_gen_add_tl(t0, arg1, arg2);
957

    
958
    if (compute_ca) {
959
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
960
    }
961
    if (add_ca) {
962
        tcg_gen_add_tl(t0, t0, t1);
963
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
964
        tcg_temp_free(t1);
965
    }
966
    if (compute_ov) {
967
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
968
    }
969

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

    
973
    if (!TCGV_EQUAL(t0, ret)) {
974
        tcg_gen_mov_tl(ret, t0);
975
        tcg_temp_free(t0);
976
    }
977
}
978
/* Add functions with two operands */
979
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
980
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER)                  \
981
{                                                                             \
982
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
983
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
984
                     add_ca, compute_ca, compute_ov);                         \
985
}
986
/* Add functions with one operand and one immediate */
987
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
988
                                add_ca, compute_ca, compute_ov)               \
989
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER)                  \
990
{                                                                             \
991
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
992
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
993
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
994
                     add_ca, compute_ca, compute_ov);                         \
995
    tcg_temp_free(t0);                                                        \
996
}
997

    
998
/* add  add.  addo  addo. */
999
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
1000
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
1001
/* addc  addc.  addco  addco. */
1002
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
1003
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
1004
/* adde  adde.  addeo  addeo. */
1005
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
1006
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
1007
/* addme  addme.  addmeo  addmeo.  */
1008
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
1009
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
1010
/* addze  addze.  addzeo  addzeo.*/
1011
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
1012
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
1013
/* addi */
1014
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1015
{
1016
    target_long simm = SIMM(ctx->opcode);
1017

    
1018
    if (rA(ctx->opcode) == 0) {
1019
        /* li case */
1020
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
1021
    } else {
1022
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
1023
    }
1024
}
1025
/* addic  addic.*/
1026
static always_inline void gen_op_addic (DisasContext *ctx, TCGv ret, TCGv arg1,
1027
                                        int compute_Rc0)
1028
{
1029
    target_long simm = SIMM(ctx->opcode);
1030

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

    
1034
    if (likely(simm != 0)) {
1035
        TCGv t0 = tcg_temp_local_new();
1036
        tcg_gen_addi_tl(t0, arg1, simm);
1037
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
1038
        tcg_gen_mov_tl(ret, t0);
1039
        tcg_temp_free(t0);
1040
    } else {
1041
        tcg_gen_mov_tl(ret, arg1);
1042
    }
1043
    if (compute_Rc0) {
1044
        gen_set_Rc0(ctx, ret);
1045
    }
1046
}
1047
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1048
{
1049
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1050
}
1051
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1052
{
1053
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1054
}
1055
/* addis */
1056
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1057
{
1058
    target_long simm = SIMM(ctx->opcode);
1059

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

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

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

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

    
1171
/* mulhw  mulhw. */
1172
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER)
1173
{
1174
    TCGv_i64 t0, t1;
1175

    
1176
    t0 = tcg_temp_new_i64();
1177
    t1 = tcg_temp_new_i64();
1178
#if defined(TARGET_PPC64)
1179
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1180
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1181
    tcg_gen_mul_i64(t0, t0, t1);
1182
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1183
#else
1184
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1185
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1186
    tcg_gen_mul_i64(t0, t0, t1);
1187
    tcg_gen_shri_i64(t0, t0, 32);
1188
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1189
#endif
1190
    tcg_temp_free_i64(t0);
1191
    tcg_temp_free_i64(t1);
1192
    if (unlikely(Rc(ctx->opcode) != 0))
1193
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1194
}
1195
/* mulhwu  mulhwu.  */
1196
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER)
1197
{
1198
    TCGv_i64 t0, t1;
1199

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

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

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

    
1333
/* Common subf function */
1334
static always_inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
1335
                                            int add_ca, int compute_ca, int compute_ov)
1336
{
1337
    TCGv t0, t1;
1338

    
1339
    if ((!compute_ca && !compute_ov) ||
1340
        (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1341
        t0 = ret;
1342
    } else {
1343
        t0 = tcg_temp_local_new();
1344
    }
1345

    
1346
    if (add_ca) {
1347
        t1 = tcg_temp_local_new();
1348
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
1349
        tcg_gen_shri_tl(t1, t1, XER_CA);
1350
    }
1351

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

    
1363
    if (add_ca) {
1364
        tcg_gen_not_tl(t0, arg1);
1365
        tcg_gen_add_tl(t0, t0, arg2);
1366
        gen_op_arith_compute_ca(ctx, t0, arg2, 0);
1367
        tcg_gen_add_tl(t0, t0, t1);
1368
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
1369
        tcg_temp_free(t1);
1370
    } else {
1371
        tcg_gen_sub_tl(t0, arg2, arg1);
1372
        if (compute_ca) {
1373
            gen_op_arith_compute_ca(ctx, t0, arg2, 1);
1374
        }
1375
    }
1376
    if (compute_ov) {
1377
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1378
    }
1379

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

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

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

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

    
1454
/* and & and. */
1455
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
1456
/* andc & andc. */
1457
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
1458
/* andi. */
1459
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1460
{
1461
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1462
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1463
}
1464
/* andis. */
1465
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1466
{
1467
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1468
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1469
}
1470
/* cntlzw */
1471
GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER)
1472
{
1473
    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1474
    if (unlikely(Rc(ctx->opcode) != 0))
1475
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1476
}
1477
/* eqv & eqv. */
1478
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
1479
/* extsb & extsb. */
1480
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
1481
/* extsh & extsh. */
1482
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
1483
/* nand & nand. */
1484
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
1485
/* nor & nor. */
1486
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
1487
/* or & or. */
1488
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
1489
{
1490
    int rs, ra, rb;
1491

    
1492
    rs = rS(ctx->opcode);
1493
    ra = rA(ctx->opcode);
1494
    rb = rB(ctx->opcode);
1495
    /* Optimisation for mr. ri case */
1496
    if (rs != ra || rs != rb) {
1497
        if (rs != rb)
1498
            tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1499
        else
1500
            tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
1501
        if (unlikely(Rc(ctx->opcode) != 0))
1502
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1503
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1504
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1505
#if defined(TARGET_PPC64)
1506
    } else {
1507
        int prio = 0;
1508

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

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

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

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

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

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

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

    
1650
    mb = MB(ctx->opcode);
1651
    me = ME(ctx->opcode);
1652
    sh = SH(ctx->opcode);
1653
    if (likely(sh == 0 && mb == 0 && me == 31)) {
1654
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1655
    } else {
1656
        target_ulong mask;
1657
        TCGv t1;
1658
        TCGv t0 = tcg_temp_new();
1659
#if defined(TARGET_PPC64)
1660
        TCGv_i32 t2 = tcg_temp_new_i32();
1661
        tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
1662
        tcg_gen_rotli_i32(t2, t2, sh);
1663
        tcg_gen_extu_i32_i64(t0, t2);
1664
        tcg_temp_free_i32(t2);
1665
#else
1666
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1667
#endif
1668
#if defined(TARGET_PPC64)
1669
        mb += 32;
1670
        me += 32;
1671
#endif
1672
        mask = MASK(mb, me);
1673
        t1 = tcg_temp_new();
1674
        tcg_gen_andi_tl(t0, t0, mask);
1675
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1676
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1677
        tcg_temp_free(t0);
1678
        tcg_temp_free(t1);
1679
    }
1680
    if (unlikely(Rc(ctx->opcode) != 0))
1681
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1682
}
1683
/* rlwinm & rlwinm. */
1684
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1685
{
1686
    uint32_t mb, me, sh;
1687

    
1688
    sh = SH(ctx->opcode);
1689
    mb = MB(ctx->opcode);
1690
    me = ME(ctx->opcode);
1691

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

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

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

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

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

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

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

    
1851
static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
1852
                                     uint32_t me)
1853
{
1854
    TCGv t0;
1855

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

    
1871
/* rldcl - rldcl. */
1872
static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1873
{
1874
    uint32_t mb;
1875

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

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

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

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

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

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

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

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

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

    
2087
/***                       Floating-Point arithmetic                       ***/
2088
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
2089
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
2090
{                                                                             \
2091
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2092
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2093
        return;                                                               \
2094
    }                                                                         \
2095
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2096
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2097
    gen_reset_fpstatus();                                                     \
2098
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
2099
                     cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
2100
    if (isfloat) {                                                            \
2101
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2102
    }                                                                         \
2103
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf,                      \
2104
                     Rc(ctx->opcode) != 0);                                   \
2105
}
2106

    
2107
#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
2108
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
2109
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
2110

    
2111
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2112
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2113
{                                                                             \
2114
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2115
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2116
        return;                                                               \
2117
    }                                                                         \
2118
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2119
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2120
    gen_reset_fpstatus();                                                     \
2121
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
2122
                     cpu_fpr[rB(ctx->opcode)]);                               \
2123
    if (isfloat) {                                                            \
2124
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2125
    }                                                                         \
2126
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2127
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2128
}
2129
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
2130
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2131
_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2132

    
2133
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2134
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2135
{                                                                             \
2136
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2137
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2138
        return;                                                               \
2139
    }                                                                         \
2140
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2141
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2142
    gen_reset_fpstatus();                                                     \
2143
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
2144
                       cpu_fpr[rC(ctx->opcode)]);                             \
2145
    if (isfloat) {                                                            \
2146
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2147
    }                                                                         \
2148
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2149
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2150
}
2151
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
2152
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2153
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2154

    
2155
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2156
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
2157
{                                                                             \
2158
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2159
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2160
        return;                                                               \
2161
    }                                                                         \
2162
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2163
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2164
    gen_reset_fpstatus();                                                     \
2165
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2166
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2167
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2168
}
2169

    
2170
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2171
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)                        \
2172
{                                                                             \
2173
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2174
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2175
        return;                                                               \
2176
    }                                                                         \
2177
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2178
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2179
    gen_reset_fpstatus();                                                     \
2180
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2181
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2182
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2183
}
2184

    
2185
/* fadd - fadds */
2186
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2187
/* fdiv - fdivs */
2188
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2189
/* fmul - fmuls */
2190
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
2191

    
2192
/* fre */
2193
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2194

    
2195
/* fres */
2196
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
2197

    
2198
/* frsqrte */
2199
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2200

    
2201
/* frsqrtes */
2202
GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES)
2203
{
2204
    if (unlikely(!ctx->fpu_enabled)) {
2205
        gen_exception(ctx, POWERPC_EXCP_FPU);
2206
        return;
2207
    }
2208
    /* NIP cannot be restored if the memory exception comes from an helper */
2209
    gen_update_nip(ctx, ctx->nip - 4);
2210
    gen_reset_fpstatus();
2211
    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2212
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2213
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2214
}
2215

    
2216
/* fsel */
2217
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2218
/* fsub - fsubs */
2219
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
2220
/* Optional: */
2221
/* fsqrt */
2222
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
2223
{
2224
    if (unlikely(!ctx->fpu_enabled)) {
2225
        gen_exception(ctx, POWERPC_EXCP_FPU);
2226
        return;
2227
    }
2228
    /* NIP cannot be restored if the memory exception comes from an helper */
2229
    gen_update_nip(ctx, ctx->nip - 4);
2230
    gen_reset_fpstatus();
2231
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2232
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2233
}
2234

    
2235
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
2236
{
2237
    if (unlikely(!ctx->fpu_enabled)) {
2238
        gen_exception(ctx, POWERPC_EXCP_FPU);
2239
        return;
2240
    }
2241
    /* NIP cannot be restored if the memory exception comes from an helper */
2242
    gen_update_nip(ctx, ctx->nip - 4);
2243
    gen_reset_fpstatus();
2244
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2245
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2246
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2247
}
2248

    
2249
/***                     Floating-Point multiply-and-add                   ***/
2250
/* fmadd - fmadds */
2251
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2252
/* fmsub - fmsubs */
2253
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2254
/* fnmadd - fnmadds */
2255
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2256
/* fnmsub - fnmsubs */
2257
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
2258

    
2259
/***                     Floating-Point round & convert                    ***/
2260
/* fctiw */
2261
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
2262
/* fctiwz */
2263
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
2264
/* frsp */
2265
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
2266
#if defined(TARGET_PPC64)
2267
/* fcfid */
2268
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
2269
/* fctid */
2270
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
2271
/* fctidz */
2272
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
2273
#endif
2274

    
2275
/* frin */
2276
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2277
/* friz */
2278
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2279
/* frip */
2280
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2281
/* frim */
2282
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2283

    
2284
/***                         Floating-Point compare                        ***/
2285
/* fcmpo */
2286
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
2287
{
2288
    TCGv_i32 crf;
2289
    if (unlikely(!ctx->fpu_enabled)) {
2290
        gen_exception(ctx, POWERPC_EXCP_FPU);
2291
        return;
2292
    }
2293
    /* NIP cannot be restored if the memory exception comes from an helper */
2294
    gen_update_nip(ctx, ctx->nip - 4);
2295
    gen_reset_fpstatus();
2296
    crf = tcg_const_i32(crfD(ctx->opcode));
2297
    gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2298
    tcg_temp_free_i32(crf);
2299
    gen_helper_float_check_status();
2300
}
2301

    
2302
/* fcmpu */
2303
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
2304
{
2305
    TCGv_i32 crf;
2306
    if (unlikely(!ctx->fpu_enabled)) {
2307
        gen_exception(ctx, POWERPC_EXCP_FPU);
2308
        return;
2309
    }
2310
    /* NIP cannot be restored if the memory exception comes from an helper */
2311
    gen_update_nip(ctx, ctx->nip - 4);
2312
    gen_reset_fpstatus();
2313
    crf = tcg_const_i32(crfD(ctx->opcode));
2314
    gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2315
    tcg_temp_free_i32(crf);
2316
    gen_helper_float_check_status();
2317
}
2318

    
2319
/***                         Floating-point move                           ***/
2320
/* fabs */
2321
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2322
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2323

    
2324
/* fmr  - fmr. */
2325
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2326
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
2327
{
2328
    if (unlikely(!ctx->fpu_enabled)) {
2329
        gen_exception(ctx, POWERPC_EXCP_FPU);
2330
        return;
2331
    }
2332
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2333
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2334
}
2335

    
2336
/* fnabs */
2337
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2338
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2339
/* fneg */
2340
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2341
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2342

    
2343
/***                  Floating-Point status & ctrl register                ***/
2344
/* mcrfs */
2345
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
2346
{
2347
    int bfa;
2348

    
2349
    if (unlikely(!ctx->fpu_enabled)) {
2350
        gen_exception(ctx, POWERPC_EXCP_FPU);
2351
        return;
2352
    }
2353
    bfa = 4 * (7 - crfS(ctx->opcode));
2354
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
2355
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2356
    tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
2357
}
2358

    
2359
/* mffs */
2360
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
2361
{
2362
    if (unlikely(!ctx->fpu_enabled)) {
2363
        gen_exception(ctx, POWERPC_EXCP_FPU);
2364
        return;
2365
    }
2366
    gen_reset_fpstatus();
2367
    tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2368
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2369
}
2370

    
2371
/* mtfsb0 */
2372
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
2373
{
2374
    uint8_t crb;
2375

    
2376
    if (unlikely(!ctx->fpu_enabled)) {
2377
        gen_exception(ctx, POWERPC_EXCP_FPU);
2378
        return;
2379
    }
2380
    crb = 31 - crbD(ctx->opcode);
2381
    gen_reset_fpstatus();
2382
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2383
        TCGv_i32 t0;
2384
        /* NIP cannot be restored if the memory exception comes from an helper */
2385
        gen_update_nip(ctx, ctx->nip - 4);
2386
        t0 = tcg_const_i32(crb);
2387
        gen_helper_fpscr_clrbit(t0);
2388
        tcg_temp_free_i32(t0);
2389
    }
2390
    if (unlikely(Rc(ctx->opcode) != 0)) {
2391
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2392
    }
2393
}
2394

    
2395
/* mtfsb1 */
2396
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
2397
{
2398
    uint8_t crb;
2399

    
2400
    if (unlikely(!ctx->fpu_enabled)) {
2401
        gen_exception(ctx, POWERPC_EXCP_FPU);
2402
        return;
2403
    }
2404
    crb = 31 - crbD(ctx->opcode);
2405
    gen_reset_fpstatus();
2406
    /* XXX: we pretend we can only do IEEE floating-point computations */
2407
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2408
        TCGv_i32 t0;
2409
        /* NIP cannot be restored if the memory exception comes from an helper */
2410
        gen_update_nip(ctx, ctx->nip - 4);
2411
        t0 = tcg_const_i32(crb);
2412
        gen_helper_fpscr_setbit(t0);
2413
        tcg_temp_free_i32(t0);
2414
    }
2415
    if (unlikely(Rc(ctx->opcode) != 0)) {
2416
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2417
    }
2418
    /* We can raise a differed exception */
2419
    gen_helper_float_check_status();
2420
}
2421

    
2422
/* mtfsf */
2423
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT)
2424
{
2425
    TCGv_i32 t0;
2426
    int L = ctx->opcode & 0x02000000;
2427

    
2428
    if (unlikely(!ctx->fpu_enabled)) {
2429
        gen_exception(ctx, POWERPC_EXCP_FPU);
2430
        return;
2431
    }
2432
    /* NIP cannot be restored if the memory exception comes from an helper */
2433
    gen_update_nip(ctx, ctx->nip - 4);
2434
    gen_reset_fpstatus();
2435
    if (L)
2436
        t0 = tcg_const_i32(0xff);
2437
    else
2438
        t0 = tcg_const_i32(FM(ctx->opcode));
2439
    gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
2440
    tcg_temp_free_i32(t0);
2441
    if (unlikely(Rc(ctx->opcode) != 0)) {
2442
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2443
    }
2444
    /* We can raise a differed exception */
2445
    gen_helper_float_check_status();
2446
}
2447

    
2448
/* mtfsfi */
2449
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
2450
{
2451
    int bf, sh;
2452
    TCGv_i64 t0;
2453
    TCGv_i32 t1;
2454

    
2455
    if (unlikely(!ctx->fpu_enabled)) {
2456
        gen_exception(ctx, POWERPC_EXCP_FPU);
2457
        return;
2458
    }
2459
    bf = crbD(ctx->opcode) >> 2;
2460
    sh = 7 - bf;
2461
    /* NIP cannot be restored if the memory exception comes from an helper */
2462
    gen_update_nip(ctx, ctx->nip - 4);
2463
    gen_reset_fpstatus();
2464
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
2465
    t1 = tcg_const_i32(1 << sh);
2466
    gen_helper_store_fpscr(t0, t1);
2467
    tcg_temp_free_i64(t0);
2468
    tcg_temp_free_i32(t1);
2469
    if (unlikely(Rc(ctx->opcode) != 0)) {
2470
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2471
    }
2472
    /* We can raise a differed exception */
2473
    gen_helper_float_check_status();
2474
}
2475

    
2476
/***                           Addressing modes                            ***/
2477
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2478
static always_inline void gen_addr_imm_index (DisasContext *ctx, TCGv EA, target_long maskl)
2479
{
2480
    target_long simm = SIMM(ctx->opcode);
2481

    
2482
    simm &= ~maskl;
2483
    if (rA(ctx->opcode) == 0) {
2484
#if defined(TARGET_PPC64)
2485
        if (!ctx->sf_mode) {
2486
            tcg_gen_movi_tl(EA, (uint32_t)simm);
2487
        } else
2488
#endif
2489
        tcg_gen_movi_tl(EA, simm);
2490
    } else if (likely(simm != 0)) {
2491
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2492
#if defined(TARGET_PPC64)
2493
        if (!ctx->sf_mode) {
2494
            tcg_gen_ext32u_tl(EA, EA);
2495
        }
2496
#endif
2497
    } else {
2498
#if defined(TARGET_PPC64)
2499
        if (!ctx->sf_mode) {
2500
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2501
        } else
2502
#endif
2503
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2504
    }
2505
}
2506

    
2507
static always_inline void gen_addr_reg_index (DisasContext *ctx, TCGv EA)
2508
{
2509
    if (rA(ctx->opcode) == 0) {
2510
#if defined(TARGET_PPC64)
2511
        if (!ctx->sf_mode) {
2512
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2513
        } else
2514
#endif
2515
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2516
    } else {
2517
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2518
#if defined(TARGET_PPC64)
2519
        if (!ctx->sf_mode) {
2520
            tcg_gen_ext32u_tl(EA, EA);
2521
        }
2522
#endif
2523
    }
2524
}
2525

    
2526
static always_inline void gen_addr_register (DisasContext *ctx, TCGv EA)
2527
{
2528
    if (rA(ctx->opcode) == 0) {
2529
        tcg_gen_movi_tl(EA, 0);
2530
    } else {
2531
#if defined(TARGET_PPC64)
2532
        if (!ctx->sf_mode) {
2533
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2534
        } else
2535
#endif
2536
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2537
    }
2538
}
2539

    
2540
static always_inline void gen_addr_add (DisasContext *ctx, TCGv ret, TCGv arg1, target_long val)
2541
{
2542
    tcg_gen_addi_tl(ret, arg1, val);
2543
#if defined(TARGET_PPC64)
2544
    if (!ctx->sf_mode) {
2545
        tcg_gen_ext32u_tl(ret, ret);
2546
    }
2547
#endif
2548
}
2549

    
2550
static always_inline void gen_check_align (DisasContext *ctx, TCGv EA, int mask)
2551
{
2552
    int l1 = gen_new_label();
2553
    TCGv t0 = tcg_temp_new();
2554
    TCGv_i32 t1, t2;
2555
    /* NIP cannot be restored if the memory exception comes from an helper */
2556
    gen_update_nip(ctx, ctx->nip - 4);
2557
    tcg_gen_andi_tl(t0, EA, mask);
2558
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2559
    t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2560
    t2 = tcg_const_i32(0);
2561
    gen_helper_raise_exception_err(t1, t2);
2562
    tcg_temp_free_i32(t1);
2563
    tcg_temp_free_i32(t2);
2564
    gen_set_label(l1);
2565
    tcg_temp_free(t0);
2566
}
2567

    
2568
/***                             Integer load                              ***/
2569
static always_inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2570
{
2571
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2572
}
2573

    
2574
static always_inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2575
{
2576
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
2577
}
2578

    
2579
static always_inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2580
{
2581
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2582
    if (unlikely(ctx->le_mode)) {
2583
        tcg_gen_bswap16_tl(arg1, arg1);
2584
    }
2585
}
2586

    
2587
static always_inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2588
{
2589
    if (unlikely(ctx->le_mode)) {
2590
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2591
        tcg_gen_bswap16_tl(arg1, arg1);
2592
        tcg_gen_ext16s_tl(arg1, arg1);
2593
    } else {
2594
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
2595
    }
2596
}
2597

    
2598
static always_inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2599
{
2600
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2601
    if (unlikely(ctx->le_mode)) {
2602
        tcg_gen_bswap32_tl(arg1, arg1);
2603
    }
2604
}
2605

    
2606
#if defined(TARGET_PPC64)
2607
static always_inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2608
{
2609
    if (unlikely(ctx->le_mode)) {
2610
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2611
        tcg_gen_bswap32_tl(arg1, arg1);
2612
        tcg_gen_ext32s_tl(arg1, arg1);
2613
    } else
2614
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
2615
}
2616
#endif
2617

    
2618
static always_inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2619
{
2620
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
2621
    if (unlikely(ctx->le_mode)) {
2622
        tcg_gen_bswap64_i64(arg1, arg1);
2623
    }
2624
}
2625

    
2626
static always_inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
2627
{
2628
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
2629
}
2630

    
2631
static always_inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
2632
{
2633
    if (unlikely(ctx->le_mode)) {
2634
        TCGv t0 = tcg_temp_new();
2635
        tcg_gen_ext16u_tl(t0, arg1);
2636
        tcg_gen_bswap16_tl(t0, t0);
2637
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2638
        tcg_temp_free(t0);
2639
    } else {
2640
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2641
    }
2642
}
2643

    
2644
static always_inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
2645
{
2646
    if (unlikely(ctx->le_mode)) {
2647
        TCGv t0 = tcg_temp_new();
2648
        tcg_gen_ext32u_tl(t0, arg1);
2649
        tcg_gen_bswap32_tl(t0, t0);
2650
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2651
        tcg_temp_free(t0);
2652
    } else {
2653
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2654
    }
2655
}
2656

    
2657
static always_inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2658
{
2659
    if (unlikely(ctx->le_mode)) {
2660
        TCGv_i64 t0 = tcg_temp_new_i64();
2661
        tcg_gen_bswap64_i64(t0, arg1);
2662
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
2663
        tcg_temp_free_i64(t0);
2664
    } else
2665
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
2666
}
2667

    
2668
#define GEN_LD(name, ldop, opc, type)                                         \
2669
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
2670
{                                                                             \
2671
    TCGv EA;                                                                  \
2672
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2673
    EA = tcg_temp_new();                                                      \
2674
    gen_addr_imm_index(ctx, EA, 0);                                           \
2675
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2676
    tcg_temp_free(EA);                                                        \
2677
}
2678

    
2679
#define GEN_LDU(name, ldop, opc, type)                                        \
2680
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
2681
{                                                                             \
2682
    TCGv EA;                                                                  \
2683
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2684
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2685
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2686
        return;                                                               \
2687
    }                                                                         \
2688
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2689
    EA = tcg_temp_new();                                                      \
2690
    if (type == PPC_64B)                                                      \
2691
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2692
    else                                                                      \
2693
        gen_addr_imm_index(ctx, EA, 0);                                       \
2694
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2695
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2696
    tcg_temp_free(EA);                                                        \
2697
}
2698

    
2699
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
2700
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type)                     \
2701
{                                                                             \
2702
    TCGv EA;                                                                  \
2703
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2704
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2705
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2706
        return;                                                               \
2707
    }                                                                         \
2708
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2709
    EA = tcg_temp_new();                                                      \
2710
    gen_addr_reg_index(ctx, EA);                                              \
2711
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2712
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2713
    tcg_temp_free(EA);                                                        \
2714
}
2715

    
2716
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
2717
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
2718
{                                                                             \
2719
    TCGv EA;                                                                  \
2720
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2721
    EA = tcg_temp_new();                                                      \
2722
    gen_addr_reg_index(ctx, EA);                                              \
2723
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2724
    tcg_temp_free(EA);                                                        \
2725
}
2726

    
2727
#define GEN_LDS(name, ldop, op, type)                                         \
2728
GEN_LD(name, ldop, op | 0x20, type);                                          \
2729
GEN_LDU(name, ldop, op | 0x21, type);                                         \
2730
GEN_LDUX(name, ldop, 0x17, op | 0x01, type);                                  \
2731
GEN_LDX(name, ldop, 0x17, op | 0x00, type)
2732

    
2733
/* lbz lbzu lbzux lbzx */
2734
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
2735
/* lha lhau lhaux lhax */
2736
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
2737
/* lhz lhzu lhzux lhzx */
2738
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
2739
/* lwz lwzu lwzux lwzx */
2740
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2741
#if defined(TARGET_PPC64)
2742
/* lwaux */
2743
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2744
/* lwax */
2745
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2746
/* ldux */
2747
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2748
/* ldx */
2749
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
2750
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
2751
{
2752
    TCGv EA;
2753
    if (Rc(ctx->opcode)) {
2754
        if (unlikely(rA(ctx->opcode) == 0 ||
2755
                     rA(ctx->opcode) == rD(ctx->opcode))) {
2756
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2757
            return;
2758
        }
2759
    }
2760
    gen_set_access_type(ctx, ACCESS_INT);
2761
    EA = tcg_temp_new();
2762
    gen_addr_imm_index(ctx, EA, 0x03);
2763
    if (ctx->opcode & 0x02) {
2764
        /* lwa (lwau is undefined) */
2765
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2766
    } else {
2767
        /* ld - ldu */
2768
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2769
    }
2770
    if (Rc(ctx->opcode))
2771
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2772
    tcg_temp_free(EA);
2773
}
2774
/* lq */
2775
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
2776
{
2777
#if defined(CONFIG_USER_ONLY)
2778
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2779
#else
2780
    int ra, rd;
2781
    TCGv EA;
2782

    
2783
    /* Restore CPU state */
2784
    if (unlikely(ctx->mem_idx == 0)) {
2785
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2786
        return;
2787
    }
2788
    ra = rA(ctx->opcode);
2789
    rd = rD(ctx->opcode);
2790
    if (unlikely((rd & 1) || rd == ra)) {
2791
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2792
        return;
2793
    }
2794
    if (unlikely(ctx->le_mode)) {
2795
        /* Little-endian mode is not handled */
2796
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2797
        return;
2798
    }
2799
    gen_set_access_type(ctx, ACCESS_INT);
2800
    EA = tcg_temp_new();
2801
    gen_addr_imm_index(ctx, EA, 0x0F);
2802
    gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2803
    gen_addr_add(ctx, EA, EA, 8);
2804
    gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
2805
    tcg_temp_free(EA);
2806
#endif
2807
}
2808
#endif
2809

    
2810
/***                              Integer store                            ***/
2811
#define GEN_ST(name, stop, opc, type)                                         \
2812
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
2813
{                                                                             \
2814
    TCGv EA;                                                                  \
2815
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2816
    EA = tcg_temp_new();                                                      \
2817
    gen_addr_imm_index(ctx, EA, 0);                                           \
2818
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2819
    tcg_temp_free(EA);                                                        \
2820
}
2821

    
2822
#define GEN_STU(name, stop, opc, type)                                        \
2823
GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
2824
{                                                                             \
2825
    TCGv EA;                                                                  \
2826
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2827
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2828
        return;                                                               \
2829
    }                                                                         \
2830
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2831
    EA = tcg_temp_new();                                                      \
2832
    if (type == PPC_64B)                                                      \
2833
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2834
    else                                                                      \
2835
        gen_addr_imm_index(ctx, EA, 0);                                       \
2836
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2837
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2838
    tcg_temp_free(EA);                                                        \
2839
}
2840

    
2841
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
2842
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type)                     \
2843
{                                                                             \
2844
    TCGv EA;                                                                  \
2845
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2846
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2847
        return;                                                               \
2848
    }                                                                         \
2849
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2850
    EA = tcg_temp_new();                                                      \
2851
    gen_addr_reg_index(ctx, EA);                                              \
2852
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2853
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2854
    tcg_temp_free(EA);                                                        \
2855
}
2856

    
2857
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
2858
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
2859
{                                                                             \
2860
    TCGv EA;                                                                  \
2861
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2862
    EA = tcg_temp_new();                                                      \
2863
    gen_addr_reg_index(ctx, EA);                                              \
2864
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2865
    tcg_temp_free(EA);                                                        \
2866
}
2867

    
2868
#define GEN_STS(name, stop, op, type)                                         \
2869
GEN_ST(name, stop, op | 0x20, type);                                          \
2870
GEN_STU(name, stop, op | 0x21, type);                                         \
2871
GEN_STUX(name, stop, 0x17, op | 0x01, type);                                  \
2872
GEN_STX(name, stop, 0x17, op | 0x00, type)
2873

    
2874
/* stb stbu stbux stbx */
2875
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
2876
/* sth sthu sthux sthx */
2877
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
2878
/* stw stwu stwux stwx */
2879
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2880
#if defined(TARGET_PPC64)
2881
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
2882
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
2883
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2884
{
2885
    int rs;
2886
    TCGv EA;
2887

    
2888
    rs = rS(ctx->opcode);
2889
    if ((ctx->opcode & 0x3) == 0x2) {
2890
#if defined(CONFIG_USER_ONLY)
2891
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2892
#else
2893
        /* stq */
2894
        if (unlikely(ctx->mem_idx == 0)) {
2895
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2896
            return;
2897
        }
2898
        if (unlikely(rs & 1)) {
2899
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2900
            return;
2901
        }
2902
        if (unlikely(ctx->le_mode)) {
2903
            /* Little-endian mode is not handled */
2904
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2905
            return;
2906
        }
2907
        gen_set_access_type(ctx, ACCESS_INT);
2908
        EA = tcg_temp_new();
2909
        gen_addr_imm_index(ctx, EA, 0x03);
2910
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2911
        gen_addr_add(ctx, EA, EA, 8);
2912
        gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
2913
        tcg_temp_free(EA);
2914
#endif
2915
    } else {
2916
        /* std / stdu */
2917
        if (Rc(ctx->opcode)) {
2918
            if (unlikely(rA(ctx->opcode) == 0)) {
2919
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2920
                return;
2921
            }
2922
        }
2923
        gen_set_access_type(ctx, ACCESS_INT);
2924
        EA = tcg_temp_new();
2925
        gen_addr_imm_index(ctx, EA, 0x03);
2926
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2927
        if (Rc(ctx->opcode))
2928
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2929
        tcg_temp_free(EA);
2930
    }
2931
}
2932
#endif
2933
/***                Integer load and store with byte reverse               ***/
2934
/* lhbrx */
2935
static void always_inline gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
2936
{
2937
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2938
    if (likely(!ctx->le_mode)) {
2939
        tcg_gen_bswap16_tl(arg1, arg1);
2940
    }
2941
}
2942
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
2943

    
2944
/* lwbrx */
2945
static void always_inline gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
2946
{
2947
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2948
    if (likely(!ctx->le_mode)) {
2949
        tcg_gen_bswap32_tl(arg1, arg1);
2950
    }
2951
}
2952
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
2953

    
2954
/* sthbrx */
2955
static void always_inline gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
2956
{
2957
    if (likely(!ctx->le_mode)) {
2958
        TCGv t0 = tcg_temp_new();
2959
        tcg_gen_ext16u_tl(t0, arg1);
2960
        tcg_gen_bswap16_tl(t0, t0);
2961
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2962
        tcg_temp_free(t0);
2963
    } else {
2964
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2965
    }
2966
}
2967
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
2968

    
2969
/* stwbrx */
2970
static void always_inline gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
2971
{
2972
    if (likely(!ctx->le_mode)) {
2973
        TCGv t0 = tcg_temp_new();
2974
        tcg_gen_ext32u_tl(t0, arg1);
2975
        tcg_gen_bswap32_tl(t0, t0);
2976
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2977
        tcg_temp_free(t0);
2978
    } else {
2979
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2980
    }
2981
}
2982
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
2983

    
2984
/***                    Integer load and store multiple                    ***/
2985
/* lmw */
2986
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2987
{
2988
    TCGv t0;
2989
    TCGv_i32 t1;
2990
    gen_set_access_type(ctx, ACCESS_INT);
2991
    /* NIP cannot be restored if the memory exception comes from an helper */
2992
    gen_update_nip(ctx, ctx->nip - 4);
2993
    t0 = tcg_temp_new();
2994
    t1 = tcg_const_i32(rD(ctx->opcode));
2995
    gen_addr_imm_index(ctx, t0, 0);
2996
    gen_helper_lmw(t0, t1);
2997
    tcg_temp_free(t0);
2998
    tcg_temp_free_i32(t1);
2999
}
3000

    
3001
/* stmw */
3002
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
3003
{
3004
    TCGv t0;
3005
    TCGv_i32 t1;
3006
    gen_set_access_type(ctx, ACCESS_INT);
3007
    /* NIP cannot be restored if the memory exception comes from an helper */
3008
    gen_update_nip(ctx, ctx->nip - 4);
3009
    t0 = tcg_temp_new();
3010
    t1 = tcg_const_i32(rS(ctx->opcode));
3011
    gen_addr_imm_index(ctx, t0, 0);
3012
    gen_helper_stmw(t0, t1);
3013
    tcg_temp_free(t0);
3014
    tcg_temp_free_i32(t1);
3015
}
3016

    
3017
/***                    Integer load and store strings                     ***/
3018
/* lswi */
3019
/* PowerPC32 specification says we must generate an exception if
3020
 * rA is in the range of registers to be loaded.
3021
 * In an other hand, IBM says this is valid, but rA won't be loaded.
3022
 * For now, I'll follow the spec...
3023
 */
3024
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
3025
{
3026
    TCGv t0;
3027
    TCGv_i32 t1, t2;
3028
    int nb = NB(ctx->opcode);
3029
    int start = rD(ctx->opcode);
3030
    int ra = rA(ctx->opcode);
3031
    int nr;
3032

    
3033
    if (nb == 0)
3034
        nb = 32;
3035
    nr = nb / 4;
3036
    if (unlikely(((start + nr) > 32  &&
3037
                  start <= ra && (start + nr - 32) > ra) ||
3038
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
3039
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
3040
        return;
3041
    }
3042
    gen_set_access_type(ctx, ACCESS_INT);
3043
    /* NIP cannot be restored if the memory exception comes from an helper */
3044
    gen_update_nip(ctx, ctx->nip - 4);
3045
    t0 = tcg_temp_new();
3046
    gen_addr_register(ctx, t0);
3047
    t1 = tcg_const_i32(nb);
3048
    t2 = tcg_const_i32(start);
3049
    gen_helper_lsw(t0, t1, t2);
3050
    tcg_temp_free(t0);
3051
    tcg_temp_free_i32(t1);
3052
    tcg_temp_free_i32(t2);
3053
}
3054

    
3055
/* lswx */
3056
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
3057
{
3058
    TCGv t0;
3059
    TCGv_i32 t1, t2, t3;
3060
    gen_set_access_type(ctx, ACCESS_INT);
3061
    /* NIP cannot be restored if the memory exception comes from an helper */
3062
    gen_update_nip(ctx, ctx->nip - 4);
3063
    t0 = tcg_temp_new();
3064
    gen_addr_reg_index(ctx, t0);
3065
    t1 = tcg_const_i32(rD(ctx->opcode));
3066
    t2 = tcg_const_i32(rA(ctx->opcode));
3067
    t3 = tcg_const_i32(rB(ctx->opcode));
3068
    gen_helper_lswx(t0, t1, t2, t3);
3069
    tcg_temp_free(t0);
3070
    tcg_temp_free_i32(t1);
3071
    tcg_temp_free_i32(t2);
3072
    tcg_temp_free_i32(t3);
3073
}
3074

    
3075
/* stswi */
3076
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
3077
{
3078
    TCGv t0;
3079
    TCGv_i32 t1, t2;
3080
    int nb = NB(ctx->opcode);
3081
    gen_set_access_type(ctx, ACCESS_INT);
3082
    /* NIP cannot be restored if the memory exception comes from an helper */
3083
    gen_update_nip(ctx, ctx->nip - 4);
3084
    t0 = tcg_temp_new();
3085
    gen_addr_register(ctx, t0);
3086
    if (nb == 0)
3087
        nb = 32;
3088
    t1 = tcg_const_i32(nb);
3089
    t2 = tcg_const_i32(rS(ctx->opcode));
3090
    gen_helper_stsw(t0, t1, t2);
3091
    tcg_temp_free(t0);
3092
    tcg_temp_free_i32(t1);
3093
    tcg_temp_free_i32(t2);
3094
}
3095

    
3096
/* stswx */
3097
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
3098
{
3099
    TCGv t0;
3100
    TCGv_i32 t1, t2;
3101
    gen_set_access_type(ctx, ACCESS_INT);
3102
    /* NIP cannot be restored if the memory exception comes from an helper */
3103
    gen_update_nip(ctx, ctx->nip - 4);
3104
    t0 = tcg_temp_new();
3105
    gen_addr_reg_index(ctx, t0);
3106
    t1 = tcg_temp_new_i32();
3107
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
3108
    tcg_gen_andi_i32(t1, t1, 0x7F);
3109
    t2 = tcg_const_i32(rS(ctx->opcode));
3110
    gen_helper_stsw(t0, t1, t2);
3111
    tcg_temp_free(t0);
3112
    tcg_temp_free_i32(t1);
3113
    tcg_temp_free_i32(t2);
3114
}
3115

    
3116
/***                        Memory synchronisation                         ***/
3117
/* eieio */
3118
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
3119
{
3120
}
3121

    
3122
/* isync */
3123
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
3124
{
3125
    gen_stop_exception(ctx);
3126
}
3127

    
3128
/* lwarx */
3129
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
3130
{
3131
    TCGv t0;
3132
    gen_set_access_type(ctx, ACCESS_RES);
3133
    t0 = tcg_temp_local_new();
3134
    gen_addr_reg_index(ctx, t0);
3135
    gen_check_align(ctx, t0, 0x03);
3136
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
3137
    tcg_gen_mov_tl(cpu_reserve, t0);
3138
    tcg_temp_free(t0);
3139
}
3140

    
3141
/* stwcx. */
3142
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
3143
{
3144
    int l1;
3145
    TCGv t0;
3146
    gen_set_access_type(ctx, ACCESS_RES);
3147
    t0 = tcg_temp_local_new();
3148
    gen_addr_reg_index(ctx, t0);
3149
    gen_check_align(ctx, t0, 0x03);
3150
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3151
    tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3152
    tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3153
    l1 = gen_new_label();
3154
    tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3155
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3156
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3157
    gen_set_label(l1);
3158
    tcg_gen_movi_tl(cpu_reserve, -1);
3159
    tcg_temp_free(t0);
3160
}
3161

    
3162
#if defined(TARGET_PPC64)
3163
/* ldarx */
3164
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
3165
{
3166
    TCGv t0;
3167
    gen_set_access_type(ctx, ACCESS_RES);
3168
    t0 = tcg_temp_local_new();
3169
    gen_addr_reg_index(ctx, t0);
3170
    gen_check_align(ctx, t0, 0x07);
3171
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], t0);
3172
    tcg_gen_mov_tl(cpu_reserve, t0);
3173
    tcg_temp_free(t0);
3174
}
3175

    
3176
/* stdcx. */
3177
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
3178
{
3179
    int l1;
3180
    TCGv t0;
3181
    gen_set_access_type(ctx, ACCESS_RES);
3182
    t0 = tcg_temp_local_new();
3183
    gen_addr_reg_index(ctx, t0);
3184
    gen_check_align(ctx, t0, 0x07);
3185
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3186
    tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3187
    tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3188
    l1 = gen_new_label();
3189
    tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3190
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3191
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3192
    gen_set_label(l1);
3193
    tcg_gen_movi_tl(cpu_reserve, -1);
3194
    tcg_temp_free(t0);
3195
}
3196
#endif /* defined(TARGET_PPC64) */
3197

    
3198
/* sync */
3199
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
3200
{
3201
}
3202

    
3203
/* wait */
3204
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
3205
{
3206
    TCGv_i32 t0 = tcg_temp_new_i32();
3207
    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
3208
    tcg_temp_free_i32(t0);
3209
    /* Stop translation, as the CPU is supposed to sleep from now */
3210
    gen_exception_err(ctx, EXCP_HLT, 1);
3211
}
3212

    
3213
/***                         Floating-point load                           ***/
3214
#define GEN_LDF(name, ldop, opc, type)                                        \
3215
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
3216
{                                                                             \
3217
    TCGv EA;                                                                  \
3218
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3219
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3220
        return;                                                               \
3221
    }                                                                         \
3222
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3223
    EA = tcg_temp_new();                                                      \
3224
    gen_addr_imm_index(ctx, EA, 0);                                           \
3225
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3226
    tcg_temp_free(EA);                                                        \
3227
}
3228

    
3229
#define GEN_LDUF(name, ldop, opc, type)                                       \
3230
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
3231
{                                                                             \
3232
    TCGv EA;                                                                  \
3233
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3234
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3235
        return;                                                               \
3236
    }                                                                         \
3237
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3238
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3239
        return;                                                               \
3240
    }                                                                         \
3241
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3242
    EA = tcg_temp_new();                                                      \
3243
    gen_addr_imm_index(ctx, EA, 0);                                           \
3244
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3245
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3246
    tcg_temp_free(EA);                                                        \
3247
}
3248

    
3249
#define GEN_LDUXF(name, ldop, opc, type)                                      \
3250
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type)                      \
3251
{                                                                             \
3252
    TCGv EA;                                                                  \
3253
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3254
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3255
        return;                                                               \
3256
    }                                                                         \
3257
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3258
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3259
        return;                                                               \
3260
    }                                                                         \
3261
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3262
    EA = tcg_temp_new();                                                      \
3263
    gen_addr_reg_index(ctx, EA);                                              \
3264
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3265
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3266
    tcg_temp_free(EA);                                                        \
3267
}
3268

    
3269
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
3270
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
3271
{                                                                             \
3272
    TCGv EA;                                                                  \
3273
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3274
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3275
        return;                                                               \
3276
    }                                                                         \
3277
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3278
    EA = tcg_temp_new();                                                      \
3279
    gen_addr_reg_index(ctx, EA);                                              \
3280
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3281
    tcg_temp_free(EA);                                                        \
3282
}
3283

    
3284
#define GEN_LDFS(name, ldop, op, type)                                        \
3285
GEN_LDF(name, ldop, op | 0x20, type);                                         \
3286
GEN_LDUF(name, ldop, op | 0x21, type);                                        \
3287
GEN_LDUXF(name, ldop, op | 0x01, type);                                       \
3288
GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3289

    
3290
static always_inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3291
{
3292
    TCGv t0 = tcg_temp_new();
3293
    TCGv_i32 t1 = tcg_temp_new_i32();
3294
    gen_qemu_ld32u(ctx, t0, arg2);
3295
    tcg_gen_trunc_tl_i32(t1, t0);
3296
    tcg_temp_free(t0);
3297
    gen_helper_float32_to_float64(arg1, t1);
3298
    tcg_temp_free_i32(t1);
3299
}
3300

    
3301
 /* lfd lfdu lfdux lfdx */
3302
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3303
 /* lfs lfsu lfsux lfsx */
3304
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
3305

    
3306
/***                         Floating-point store                          ***/
3307
#define GEN_STF(name, stop, opc, type)                                        \
3308
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
3309
{                                                                             \
3310
    TCGv EA;                                                                  \
3311
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3312
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3313
        return;                                                               \
3314
    }                                                                         \
3315
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3316
    EA = tcg_temp_new();                                                      \
3317
    gen_addr_imm_index(ctx, EA, 0);                                           \
3318
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3319
    tcg_temp_free(EA);                                                        \
3320
}
3321

    
3322
#define GEN_STUF(name, stop, opc, type)                                       \
3323
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
3324
{                                                                             \
3325
    TCGv EA;                                                                  \
3326
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3327
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3328
        return;                                                               \
3329
    }                                                                         \
3330
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3331
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3332
        return;                                                               \
3333
    }                                                                         \
3334
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3335
    EA = tcg_temp_new();                                                      \
3336
    gen_addr_imm_index(ctx, EA, 0);                                           \
3337
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3338
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3339
    tcg_temp_free(EA);                                                        \
3340
}
3341

    
3342
#define GEN_STUXF(name, stop, opc, type)                                      \
3343
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type)                      \
3344
{                                                                             \
3345
    TCGv EA;                                                                  \
3346
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3347
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3348
        return;                                                               \
3349
    }                                                                         \
3350
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3351
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3352
        return;                                                               \
3353
    }                                                                         \
3354
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3355
    EA = tcg_temp_new();                                                      \
3356
    gen_addr_reg_index(ctx, EA);                                              \
3357
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3358
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3359
    tcg_temp_free(EA);                                                        \
3360
}
3361

    
3362
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
3363
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
3364
{                                                                             \
3365
    TCGv EA;                                                                  \
3366
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3367
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3368
        return;                                                               \
3369
    }                                                                         \
3370
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3371
    EA = tcg_temp_new();                                                      \
3372
    gen_addr_reg_index(ctx, EA);                                              \
3373
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3374
    tcg_temp_free(EA);                                                        \
3375
}
3376

    
3377
#define GEN_STFS(name, stop, op, type)                                        \
3378
GEN_STF(name, stop, op | 0x20, type);                                         \
3379
GEN_STUF(name, stop, op | 0x21, type);                                        \
3380
GEN_STUXF(name, stop, op | 0x01, type);                                       \
3381
GEN_STXF(name, stop, 0x17, op | 0x00, type)
3382

    
3383
static always_inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3384
{
3385
    TCGv_i32 t0 = tcg_temp_new_i32();
3386
    TCGv t1 = tcg_temp_new();
3387
    gen_helper_float64_to_float32(t0, arg1);
3388
    tcg_gen_extu_i32_tl(t1, t0);
3389
    tcg_temp_free_i32(t0);
3390
    gen_qemu_st32(ctx, t1, arg2);
3391
    tcg_temp_free(t1);
3392
}
3393

    
3394
/* stfd stfdu stfdux stfdx */
3395
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
3396
/* stfs stfsu stfsux stfsx */
3397
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
3398

    
3399
/* Optional: */
3400
static always_inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3401
{
3402
    TCGv t0 = tcg_temp_new();
3403
    tcg_gen_trunc_i64_tl(t0, arg1),
3404
    gen_qemu_st32(ctx, t0, arg2);
3405
    tcg_temp_free(t0);
3406
}
3407
/* stfiwx */
3408
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
3409

    
3410
/***                                Branch                                 ***/
3411
static always_inline void gen_goto_tb (DisasContext *ctx, int n,
3412
                                       target_ulong dest)
3413
{
3414
    TranslationBlock *tb;
3415
    tb = ctx->tb;
3416
#if defined(TARGET_PPC64)
3417
    if (!ctx->sf_mode)
3418
        dest = (uint32_t) dest;
3419
#endif
3420
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3421
        likely(!ctx->singlestep_enabled)) {
3422
        tcg_gen_goto_tb(n);
3423
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3424
        tcg_gen_exit_tb((long)tb + n);
3425
    } else {
3426
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3427
        if (unlikely(ctx->singlestep_enabled)) {
3428
            if ((ctx->singlestep_enabled &
3429
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3430
                ctx->exception == POWERPC_EXCP_BRANCH) {
3431
                target_ulong tmp = ctx->nip;
3432
                ctx->nip = dest;
3433
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3434
                ctx->nip = tmp;
3435
            }
3436
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3437
                gen_debug_exception(ctx);
3438
            }
3439
        }
3440
        tcg_gen_exit_tb(0);
3441
    }
3442
}
3443

    
3444
static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
3445
{
3446
#if defined(TARGET_PPC64)
3447
    if (ctx->sf_mode == 0)
3448
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3449
    else
3450
#endif
3451
        tcg_gen_movi_tl(cpu_lr, nip);
3452
}
3453

    
3454
/* b ba bl bla */
3455
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3456
{
3457
    target_ulong li, target;
3458

    
3459
    ctx->exception = POWERPC_EXCP_BRANCH;
3460
    /* sign extend LI */
3461
#if defined(TARGET_PPC64)
3462
    if (ctx->sf_mode)
3463
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3464
    else
3465
#endif
3466
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3467
    if (likely(AA(ctx->opcode) == 0))
3468
        target = ctx->nip + li - 4;
3469
    else
3470
        target = li;
3471
    if (LK(ctx->opcode))
3472
        gen_setlr(ctx, ctx->nip);
3473
    gen_goto_tb(ctx, 0, target);
3474
}
3475

    
3476
#define BCOND_IM  0
3477
#define BCOND_LR  1
3478
#define BCOND_CTR 2
3479

    
3480
static always_inline void gen_bcond (DisasContext *ctx, int type)
3481
{
3482
    uint32_t bo = BO(ctx->opcode);
3483
    int l1 = gen_new_label();
3484
    TCGv target;
3485

    
3486
    ctx->exception = POWERPC_EXCP_BRANCH;
3487
    if (type == BCOND_LR || type == BCOND_CTR) {
3488
        target = tcg_temp_local_new();
3489
        if (type == BCOND_CTR)
3490
            tcg_gen_mov_tl(target, cpu_ctr);
3491
        else
3492
            tcg_gen_mov_tl(target, cpu_lr);
3493
    }
3494
    if (LK(ctx->opcode))
3495
        gen_setlr(ctx, ctx->nip);
3496
    l1 = gen_new_label();
3497
    if ((bo & 0x4) == 0) {
3498
        /* Decrement and test CTR */
3499
        TCGv temp = tcg_temp_new();
3500
        if (unlikely(type == BCOND_CTR)) {
3501
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3502
            return;
3503
        }
3504
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3505
#if defined(TARGET_PPC64)
3506
        if (!ctx->sf_mode)
3507
            tcg_gen_ext32u_tl(temp, cpu_ctr);
3508
        else
3509
#endif
3510
            tcg_gen_mov_tl(temp, cpu_ctr);
3511
        if (bo & 0x2) {
3512
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3513
        } else {
3514
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3515
        }
3516
        tcg_temp_free(temp);
3517
    }
3518
    if ((bo & 0x10) == 0) {
3519
        /* Test CR */
3520
        uint32_t bi = BI(ctx->opcode);
3521
        uint32_t mask = 1 << (3 - (bi & 0x03));
3522
        TCGv_i32 temp = tcg_temp_new_i32();
3523

    
3524
        if (bo & 0x8) {
3525
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3526
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3527
        } else {
3528
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3529
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3530
        }
3531
        tcg_temp_free_i32(temp);
3532
    }
3533
    if (type == BCOND_IM) {
3534
        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3535
        if (likely(AA(ctx->opcode) == 0)) {
3536
            gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3537
        } else {
3538
            gen_goto_tb(ctx, 0, li);
3539
        }
3540
        gen_set_label(l1);
3541
        gen_goto_tb(ctx, 1, ctx->nip);
3542
    } else {
3543
#if defined(TARGET_PPC64)
3544
        if (!(ctx->sf_mode))
3545
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3546
        else
3547
#endif
3548
            tcg_gen_andi_tl(cpu_nip, target, ~3);
3549
        tcg_gen_exit_tb(0);
3550
        gen_set_label(l1);
3551
#if defined(TARGET_PPC64)
3552
        if (!(ctx->sf_mode))
3553
            tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
3554
        else
3555
#endif
3556
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
3557
        tcg_gen_exit_tb(0);
3558
    }
3559
}
3560

    
3561
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3562
{
3563
    gen_bcond(ctx, BCOND_IM);
3564
}
3565

    
3566
GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3567
{
3568
    gen_bcond(ctx, BCOND_CTR);
3569
}
3570

    
3571
GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3572
{
3573
    gen_bcond(ctx, BCOND_LR);
3574
}
3575

    
3576
/***                      Condition register logical                       ***/
3577
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
3578
GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)                   \
3579
{                                                                             \
3580
    uint8_t bitmask;                                                          \
3581
    int sh;                                                                   \
3582
    TCGv_i32 t0, t1;                                                          \
3583
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
3584
    t0 = tcg_temp_new_i32();                                                  \
3585
    if (sh > 0)                                                               \
3586
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3587
    else if (sh < 0)                                                          \
3588
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3589
    else                                                                      \
3590
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
3591
    t1 = tcg_temp_new_i32();                                                  \
3592
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
3593
    if (sh > 0)                                                               \
3594
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3595
    else if (sh < 0)                                                          \
3596
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3597
    else                                                                      \
3598
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
3599
    tcg_op(t0, t0, t1);                                                       \
3600
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3601
    tcg_gen_andi_i32(t0, t0, bitmask);                                        \
3602
    tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask);          \
3603
    tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1);                  \
3604
    tcg_temp_free_i32(t0);                                                    \
3605
    tcg_temp_free_i32(t1);                                                    \
3606
}
3607

    
3608
/* crand */
3609
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
3610
/* crandc */
3611
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
3612
/* creqv */
3613
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
3614
/* crnand */
3615
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
3616
/* crnor */
3617
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
3618
/* cror */
3619
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
3620
/* crorc */
3621
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
3622
/* crxor */
3623
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
3624
/* mcrf */
3625
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
3626
{
3627
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
3628
}
3629

    
3630
/***                           System linkage                              ***/
3631
/* rfi (mem_idx only) */
3632
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
3633
{
3634
#if defined(CONFIG_USER_ONLY)
3635
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3636
#else
3637
    /* Restore CPU state */
3638
    if (unlikely(!ctx->mem_idx)) {
3639
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3640
        return;
3641
    }
3642
    gen_helper_rfi();
3643
    gen_sync_exception(ctx);
3644
#endif
3645
}
3646

    
3647
#if defined(TARGET_PPC64)
3648
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
3649
{
3650
#if defined(CONFIG_USER_ONLY)
3651
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3652
#else
3653
    /* Restore CPU state */
3654
    if (unlikely(!ctx->mem_idx)) {
3655
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3656
        return;
3657
    }
3658
    gen_helper_rfid();
3659
    gen_sync_exception(ctx);
3660
#endif
3661
}
3662

    
3663
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
3664
{
3665
#if defined(CONFIG_USER_ONLY)
3666
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3667
#else
3668
    /* Restore CPU state */
3669
    if (unlikely(ctx->mem_idx <= 1)) {
3670
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3671
        return;
3672
    }
3673
    gen_helper_hrfid();
3674
    gen_sync_exception(ctx);
3675
#endif
3676
}
3677
#endif
3678

    
3679
/* sc */
3680
#if defined(CONFIG_USER_ONLY)
3681
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3682
#else
3683
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3684
#endif
3685
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
3686
{
3687
    uint32_t lev;
3688

    
3689
    lev = (ctx->opcode >> 5) & 0x7F;
3690
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
3691
}
3692

    
3693
/***                                Trap                                   ***/
3694
/* tw */
3695
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
3696
{
3697
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3698
    /* Update the nip since this might generate a trap exception */
3699
    gen_update_nip(ctx, ctx->nip);
3700
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3701
    tcg_temp_free_i32(t0);
3702
}
3703

    
3704
/* twi */
3705
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3706
{
3707
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3708
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3709
    /* Update the nip since this might generate a trap exception */
3710
    gen_update_nip(ctx, ctx->nip);
3711
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
3712
    tcg_temp_free(t0);
3713
    tcg_temp_free_i32(t1);
3714
}
3715

    
3716
#if defined(TARGET_PPC64)
3717
/* td */
3718
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
3719
{
3720
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3721
    /* Update the nip since this might generate a trap exception */
3722
    gen_update_nip(ctx, ctx->nip);
3723
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3724
    tcg_temp_free_i32(t0);
3725
}
3726

    
3727
/* tdi */
3728
GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
3729
{
3730
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3731
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3732
    /* Update the nip since this might generate a trap exception */
3733
    gen_update_nip(ctx, ctx->nip);
3734
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
3735
    tcg_temp_free(t0);
3736
    tcg_temp_free_i32(t1);
3737
}
3738
#endif
3739

    
3740
/***                          Processor control                            ***/
3741
/* mcrxr */
3742
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
3743
{
3744
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
3745
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3746
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
3747
}
3748

    
3749
/* mfcr mfocrf */
3750
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
3751
{
3752
    uint32_t crm, crn;
3753

    
3754
    if (likely(ctx->opcode & 0x00100000)) {
3755
        crm = CRM(ctx->opcode);
3756
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
3757
            crn = ctz32 (crm);
3758
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
3759
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
3760
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3761
        }
3762
    } else {
3763
        TCGv_i32 t0 = tcg_temp_new_i32();
3764
        tcg_gen_mov_i32(t0, cpu_crf[0]);
3765
        tcg_gen_shli_i32(t0, t0, 4);
3766
        tcg_gen_or_i32(t0, t0, cpu_crf[1]);
3767
        tcg_gen_shli_i32(t0, t0, 4);
3768
        tcg_gen_or_i32(t0, t0, cpu_crf[2]);
3769
        tcg_gen_shli_i32(t0, t0, 4);
3770
        tcg_gen_or_i32(t0, t0, cpu_crf[3]);
3771
        tcg_gen_shli_i32(t0, t0, 4);
3772
        tcg_gen_or_i32(t0, t0, cpu_crf[4]);
3773
        tcg_gen_shli_i32(t0, t0, 4);
3774
        tcg_gen_or_i32(t0, t0, cpu_crf[5]);
3775
        tcg_gen_shli_i32(t0, t0, 4);
3776
        tcg_gen_or_i32(t0, t0, cpu_crf[6]);
3777
        tcg_gen_shli_i32(t0, t0, 4);
3778
        tcg_gen_or_i32(t0, t0, cpu_crf[7]);
3779
        tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
3780
        tcg_temp_free_i32(t0);
3781
    }
3782
}
3783

    
3784
/* mfmsr */
3785
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
3786
{
3787
#if defined(CONFIG_USER_ONLY)
3788
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3789
#else
3790
    if (unlikely(!ctx->mem_idx)) {
3791
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3792
        return;
3793
    }
3794
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3795
#endif
3796
}
3797

    
3798
#if 1
3799
#define SPR_NOACCESS ((void *)(-1UL))
3800
#else
3801
static void spr_noaccess (void *opaque, int sprn)
3802
{
3803
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3804
    printf("ERROR: try to access SPR %d !\n", sprn);
3805
}
3806
#define SPR_NOACCESS (&spr_noaccess)
3807
#endif
3808

    
3809
/* mfspr */
3810
static always_inline void gen_op_mfspr (DisasContext *ctx)
3811
{
3812
    void (*read_cb)(void *opaque, int gprn, int sprn);
3813
    uint32_t sprn = SPR(ctx->opcode);
3814

    
3815
#if !defined(CONFIG_USER_ONLY)
3816
    if (ctx->mem_idx == 2)
3817
        read_cb = ctx->spr_cb[sprn].hea_read;
3818
    else if (ctx->mem_idx)
3819
        read_cb = ctx->spr_cb[sprn].oea_read;
3820
    else
3821
#endif
3822
        read_cb = ctx->spr_cb[sprn].uea_read;
3823
    if (likely(read_cb != NULL)) {
3824
        if (likely(read_cb != SPR_NOACCESS)) {
3825
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3826
        } else {
3827
            /* Privilege exception */
3828
            /* This is a hack to avoid warnings when running Linux:
3829
             * this OS breaks the PowerPC virtualisation model,
3830
             * allowing userland application to read the PVR
3831
             */
3832
            if (sprn != SPR_PVR) {
3833
                qemu_log("Trying to read privileged spr %d %03x at "
3834
                            ADDRX "\n", sprn, sprn, ctx->nip);
3835
                printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
3836
                       sprn, sprn, ctx->nip);
3837
            }
3838
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3839
        }
3840
    } else {
3841
        /* Not defined */
3842
        qemu_log("Trying to read invalid spr %d %03x at "
3843
                    ADDRX "\n", sprn, sprn, ctx->nip);
3844
        printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
3845
               sprn, sprn, ctx->nip);
3846
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
3847
    }
3848
}
3849

    
3850
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
3851
{
3852
    gen_op_mfspr(ctx);
3853
}
3854

    
3855
/* mftb */
3856
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3857
{
3858
    gen_op_mfspr(ctx);
3859
}
3860

    
3861
/* mtcrf mtocrf*/
3862
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
3863
{
3864
    uint32_t crm, crn;
3865

    
3866
    crm = CRM(ctx->opcode);
3867
    if (likely((ctx->opcode & 0x00100000))) {
3868
        if (crm && ((crm & (crm - 1)) == 0)) {
3869
            TCGv_i32 temp = tcg_temp_new_i32();
3870
            crn = ctz32 (crm);
3871
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3872
            tcg_gen_shri_i32(temp, temp, crn * 4);
3873
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
3874
            tcg_temp_free_i32(temp);
3875
        }
3876
    } else {
3877
        TCGv_i32 temp = tcg_temp_new_i32();
3878
        tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3879
        for (crn = 0 ; crn < 8 ; crn++) {
3880
            if (crm & (1 << crn)) {
3881
                    tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
3882
                    tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3883
            }
3884
        }
3885
        tcg_temp_free_i32(temp);
3886
    }
3887
}
3888

    
3889
/* mtmsr */
3890
#if defined(TARGET_PPC64)
3891
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
3892
{
3893
#if defined(CONFIG_USER_ONLY)
3894
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3895
#else
3896
    if (unlikely(!ctx->mem_idx)) {
3897
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3898
        return;
3899
    }
3900
    if (ctx->opcode & 0x00010000) {
3901
        /* Special form that does not need any synchronisation */
3902
        TCGv t0 = tcg_temp_new();
3903
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3904
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3905
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3906
        tcg_temp_free(t0);
3907
    } else {
3908
        /* XXX: we need to update nip before the store
3909
         *      if we enter power saving mode, we will exit the loop
3910
         *      directly from ppc_store_msr
3911
         */
3912
        gen_update_nip(ctx, ctx->nip);
3913
        gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3914
        /* Must stop the translation as machine state (may have) changed */
3915
        /* Note that mtmsr is not always defined as context-synchronizing */
3916
        gen_stop_exception(ctx);
3917
    }
3918
#endif
3919
}
3920
#endif
3921

    
3922
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
3923
{
3924
#if defined(CONFIG_USER_ONLY)
3925
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3926
#else
3927
    if (unlikely(!ctx->mem_idx)) {
3928
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3929
        return;
3930
    }
3931
    if (ctx->opcode & 0x00010000) {
3932
        /* Special form that does not need any synchronisation */
3933
        TCGv t0 = tcg_temp_new();
3934
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3935
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3936
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3937
        tcg_temp_free(t0);
3938
    } else {
3939
        /* XXX: we need to update nip before the store
3940
         *      if we enter power saving mode, we will exit the loop
3941
         *      directly from ppc_store_msr
3942
         */
3943
        gen_update_nip(ctx, ctx->nip);
3944
#if defined(TARGET_PPC64)
3945
        if (!ctx->sf_mode) {
3946
            TCGv t0 = tcg_temp_new();
3947
            TCGv t1 = tcg_temp_new();
3948
            tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
3949
            tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
3950
            tcg_gen_or_tl(t0, t0, t1);
3951
            tcg_temp_free(t1);
3952
            gen_helper_store_msr(t0);
3953
            tcg_temp_free(t0);
3954
        } else
3955
#endif
3956
            gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3957
        /* Must stop the translation as machine state (may have) changed */
3958
        /* Note that mtmsr is not always defined as context-synchronizing */
3959
        gen_stop_exception(ctx);
3960
    }
3961
#endif
3962
}
3963

    
3964
/* mtspr */
3965
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
3966
{
3967
    void (*write_cb)(void *opaque, int sprn, int gprn);
3968
    uint32_t sprn = SPR(ctx->opcode);
3969

    
3970
#if !defined(CONFIG_USER_ONLY)
3971
    if (ctx->mem_idx == 2)
3972
        write_cb = ctx->spr_cb[sprn].hea_write;
3973
    else if (ctx->mem_idx)
3974
        write_cb = ctx->spr_cb[sprn].oea_write;
3975
    else
3976
#endif
3977
        write_cb = ctx->spr_cb[sprn].uea_write;
3978
    if (likely(write_cb != NULL)) {
3979
        if (likely(write_cb != SPR_NOACCESS)) {
3980
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
3981
        } else {
3982
            /* Privilege exception */
3983
            qemu_log("Trying to write privileged spr %d %03x at "
3984
                        ADDRX "\n", sprn, sprn, ctx->nip);
3985
            printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
3986
                   sprn, sprn, ctx->nip);
3987
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3988
        }
3989
    } else {
3990
        /* Not defined */
3991
        qemu_log("Trying to write invalid spr %d %03x at "
3992
                    ADDRX "\n", sprn, sprn, ctx->nip);
3993
        printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
3994
               sprn, sprn, ctx->nip);
3995
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
3996
    }
3997
}
3998

    
3999
/***                         Cache management                              ***/
4000
/* dcbf */
4001
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
4002
{
4003
    /* XXX: specification says this is treated as a load by the MMU */
4004
    TCGv t0;
4005
    gen_set_access_type(ctx, ACCESS_CACHE);
4006
    t0 = tcg_temp_new();
4007
    gen_addr_reg_index(ctx, t0);
4008
    gen_qemu_ld8u(ctx, t0, t0);
4009
    tcg_temp_free(t0);
4010
}
4011

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

    
4035
/* dcdst */
4036
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
4037
{
4038
    /* XXX: specification say this is treated as a load by the MMU */
4039
    TCGv t0;
4040
    gen_set_access_type(ctx, ACCESS_CACHE);
4041
    t0 = tcg_temp_new();
4042
    gen_addr_reg_index(ctx, t0);
4043
    gen_qemu_ld8u(ctx, t0, t0);
4044
    tcg_temp_free(t0);
4045
}
4046

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

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

    
4065
/* dcbz */
4066
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
4067
{
4068
    TCGv t0;
4069
    gen_set_access_type(ctx, ACCESS_CACHE);
4070
    /* NIP cannot be restored if the memory exception comes from an helper */
4071
    gen_update_nip(ctx, ctx->nip - 4);
4072
    t0 = tcg_temp_new();
4073
    gen_addr_reg_index(ctx, t0);
4074
    gen_helper_dcbz(t0);
4075
    tcg_temp_free(t0);
4076
}
4077

    
4078
GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
4079
{
4080
    TCGv t0;
4081
    gen_set_access_type(ctx, ACCESS_CACHE);
4082
    /* NIP cannot be restored if the memory exception comes from an helper */
4083
    gen_update_nip(ctx, ctx->nip - 4);
4084
    t0 = tcg_temp_new();
4085
    gen_addr_reg_index(ctx, t0);
4086
    if (ctx->opcode & 0x00200000)
4087
        gen_helper_dcbz(t0);
4088
    else
4089
        gen_helper_dcbz_970(t0);
4090
    tcg_temp_free(t0);
4091
}
4092

    
4093
/* dst / dstt */
4094
GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC)
4095
{
4096
    if (rA(ctx->opcode) == 0) {
4097
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4098
    } else {
4099
        /* interpreted as no-op */
4100
    }
4101
}
4102

    
4103
/* dstst /dststt */
4104
GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC)
4105
{
4106
    if (rA(ctx->opcode) == 0) {
4107
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4108
    } else {
4109
        /* interpreted as no-op */
4110
    }
4111

    
4112
}
4113

    
4114
/* dss / dssall */
4115
GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC)
4116
{
4117
    /* interpreted as no-op */
4118
}
4119

    
4120
/* icbi */
4121
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
4122
{
4123
    TCGv t0;
4124
    gen_set_access_type(ctx, ACCESS_CACHE);
4125
    /* NIP cannot be restored if the memory exception comes from an helper */
4126
    gen_update_nip(ctx, ctx->nip - 4);
4127
    t0 = tcg_temp_new();
4128
    gen_addr_reg_index(ctx, t0);
4129
    gen_helper_icbi(t0);
4130
    tcg_temp_free(t0);
4131
}
4132

    
4133
/* Optional: */
4134
/* dcba */
4135
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
4136
{
4137
    /* interpreted as no-op */
4138
    /* XXX: specification say this is treated as a store by the MMU
4139
     *      but does not generate any exception
4140
     */
4141
}
4142

    
4143
/***                    Segment register manipulation                      ***/
4144
/* Supervisor only: */
4145
/* mfsr */
4146
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
4147
{
4148
#if defined(CONFIG_USER_ONLY)
4149
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4150
#else
4151
    TCGv t0;
4152
    if (unlikely(!ctx->mem_idx)) {
4153
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4154
        return;
4155
    }
4156
    t0 = tcg_const_tl(SR(ctx->opcode));
4157
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4158
    tcg_temp_free(t0);
4159
#endif
4160
}
4161

    
4162
/* mfsrin */
4163
GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
4164
{
4165
#if defined(CONFIG_USER_ONLY)
4166
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4167
#else
4168
    TCGv t0;
4169
    if (unlikely(!ctx->mem_idx)) {
4170
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4171
        return;
4172
    }
4173
    t0 = tcg_temp_new();
4174
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4175
    tcg_gen_andi_tl(t0, t0, 0xF);
4176
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4177
    tcg_temp_free(t0);
4178
#endif
4179
}
4180

    
4181
/* mtsr */
4182
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
4183
{
4184
#if defined(CONFIG_USER_ONLY)
4185
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4186
#else
4187
    TCGv t0;
4188
    if (unlikely(!ctx->mem_idx)) {
4189
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4190
        return;
4191
    }
4192
    t0 = tcg_const_tl(SR(ctx->opcode));
4193
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4194
    tcg_temp_free(t0);
4195
#endif
4196
}
4197

    
4198
/* mtsrin */
4199
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
4200
{
4201
#if defined(CONFIG_USER_ONLY)
4202
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4203
#else
4204
    TCGv t0;
4205
    if (unlikely(!ctx->mem_idx)) {
4206
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4207
        return;
4208
    }
4209
    t0 = tcg_temp_new();
4210
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4211
    tcg_gen_andi_tl(t0, t0, 0xF);
4212
    gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
4213
    tcg_temp_free(t0);
4214
#endif
4215
}
4216

    
4217
#if defined(TARGET_PPC64)
4218
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
4219
/* mfsr */
4220
GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
4221
{
4222
#if defined(CONFIG_USER_ONLY)
4223
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4224
#else
4225
    TCGv t0;
4226
    if (unlikely(!ctx->mem_idx)) {
4227
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4228
        return;
4229
    }
4230
    t0 = tcg_const_tl(SR(ctx->opcode));
4231
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4232
    tcg_temp_free(t0);
4233
#endif
4234
}
4235

    
4236
/* mfsrin */
4237
GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
4238
             PPC_SEGMENT_64B)
4239
{
4240
#if defined(CONFIG_USER_ONLY)
4241
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4242
#else
4243
    TCGv t0;
4244
    if (unlikely(!ctx->mem_idx)) {
4245
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4246
        return;
4247
    }
4248
    t0 = tcg_temp_new();
4249
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4250
    tcg_gen_andi_tl(t0, t0, 0xF);
4251
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4252
    tcg_temp_free(t0);
4253
#endif
4254
}
4255

    
4256
/* mtsr */
4257
GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
4258
{
4259
#if defined(CONFIG_USER_ONLY)
4260
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4261
#else
4262
    TCGv t0;
4263
    if (unlikely(!ctx->mem_idx)) {
4264
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4265
        return;
4266
    }
4267
    t0 = tcg_const_tl(SR(ctx->opcode));
4268
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4269
    tcg_temp_free(t0);
4270
#endif
4271
}
4272

    
4273
/* mtsrin */
4274
GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
4275
             PPC_SEGMENT_64B)
4276
{
4277
#if defined(CONFIG_USER_ONLY)
4278
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4279
#else
4280
    TCGv t0;
4281
    if (unlikely(!ctx->mem_idx)) {
4282
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4283
        return;
4284
    }
4285
    t0 = tcg_temp_new();
4286
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4287
    tcg_gen_andi_tl(t0, t0, 0xF);
4288
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4289
    tcg_temp_free(t0);
4290
#endif
4291
}
4292

    
4293
/* slbmte */
4294
GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B)
4295
{
4296
#if defined(CONFIG_USER_ONLY)
4297
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4298
#else
4299
    if (unlikely(!ctx->mem_idx)) {
4300
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4301
        return;
4302
    }
4303
    gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
4304
#endif
4305
}
4306

    
4307
#endif /* defined(TARGET_PPC64) */
4308

    
4309
/***                      Lookaside buffer management                      ***/
4310
/* Optional & mem_idx only: */
4311
/* tlbia */
4312
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
4313
{
4314
#if defined(CONFIG_USER_ONLY)
4315
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4316
#else
4317
    if (unlikely(!ctx->mem_idx)) {
4318
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4319
        return;
4320
    }
4321
    gen_helper_tlbia();
4322
#endif
4323
}
4324

    
4325
/* tlbiel */
4326
GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE)
4327
{
4328
#if defined(CONFIG_USER_ONLY)
4329
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4330
#else
4331
    if (unlikely(!ctx->mem_idx)) {
4332
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4333
        return;
4334
    }
4335
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4336
#endif
4337
}
4338

    
4339
/* tlbie */
4340
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
4341
{
4342
#if defined(CONFIG_USER_ONLY)
4343
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4344
#else
4345
    if (unlikely(!ctx->mem_idx)) {
4346
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4347
        return;
4348
    }
4349
#if defined(TARGET_PPC64)
4350
    if (!ctx->sf_mode) {
4351
        TCGv t0 = tcg_temp_new();
4352
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4353
        gen_helper_tlbie(t0);
4354
        tcg_temp_free(t0);
4355
    } else
4356
#endif
4357
        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4358
#endif
4359
}
4360

    
4361
/* tlbsync */
4362
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
4363
{
4364
#if defined(CONFIG_USER_ONLY)
4365
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4366
#else
4367
    if (unlikely(!ctx->mem_idx)) {
4368
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4369
        return;
4370
    }
4371
    /* This has no effect: it should ensure that all previous
4372
     * tlbie have completed
4373
     */
4374
    gen_stop_exception(ctx);
4375
#endif
4376
}
4377

    
4378
#if defined(TARGET_PPC64)
4379
/* slbia */
4380
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
4381
{
4382
#if defined(CONFIG_USER_ONLY)
4383
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4384
#else
4385
    if (unlikely(!ctx->mem_idx)) {
4386
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4387
        return;
4388
    }
4389
    gen_helper_slbia();
4390
#endif
4391
}
4392

    
4393
/* slbie */
4394
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
4395
{
4396
#if defined(CONFIG_USER_ONLY)
4397
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4398
#else
4399
    if (unlikely(!ctx->mem_idx)) {
4400
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4401
        return;
4402
    }
4403
    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
4404
#endif
4405
}
4406
#endif
4407

    
4408
/***                              External control                         ***/
4409
/* Optional: */
4410
/* eciwx */
4411
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
4412
{
4413
    TCGv t0;
4414
    /* Should check EAR[E] ! */
4415
    gen_set_access_type(ctx, ACCESS_EXT);
4416
    t0 = tcg_temp_new();
4417
    gen_addr_reg_index(ctx, t0);
4418
    gen_check_align(ctx, t0, 0x03);
4419
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4420
    tcg_temp_free(t0);
4421
}
4422

    
4423
/* ecowx */
4424
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
4425
{
4426
    TCGv t0;
4427
    /* Should check EAR[E] ! */
4428
    gen_set_access_type(ctx, ACCESS_EXT);
4429
    t0 = tcg_temp_new();
4430
    gen_addr_reg_index(ctx, t0);
4431
    gen_check_align(ctx, t0, 0x03);
4432
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4433
    tcg_temp_free(t0);
4434
}
4435

    
4436
/* PowerPC 601 specific instructions */
4437
/* abs - abs. */
4438
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
4439
{
4440
    int l1 = gen_new_label();
4441
    int l2 = gen_new_label();
4442
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4443
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4444
    tcg_gen_br(l2);
4445
    gen_set_label(l1);
4446
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4447
    gen_set_label(l2);
4448
    if (unlikely(Rc(ctx->opcode) != 0))
4449
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4450
}
4451

    
4452
/* abso - abso. */
4453
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
4454
{
4455
    int l1 = gen_new_label();
4456
    int l2 = gen_new_label();
4457
    int l3 = gen_new_label();
4458
    /* Start with XER OV disabled, the most likely case */
4459
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4460
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4461
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4462
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4463
    tcg_gen_br(l2);
4464
    gen_set_label(l1);
4465
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4466
    tcg_gen_br(l3);
4467
    gen_set_label(l2);
4468
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4469
    gen_set_label(l3);
4470
    if (unlikely(Rc(ctx->opcode) != 0))
4471
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4472
}
4473

    
4474
/* clcs */
4475
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
4476
{
4477
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4478
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
4479
    tcg_temp_free_i32(t0);
4480
    /* Rc=1 sets CR0 to an undefined state */
4481
}
4482

    
4483
/* div - div. */
4484
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
4485
{
4486
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4487
    if (unlikely(Rc(ctx->opcode) != 0))
4488
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4489
}
4490

    
4491
/* divo - divo. */
4492
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
4493
{
4494
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4495
    if (unlikely(Rc(ctx->opcode) != 0))
4496
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4497
}
4498

    
4499
/* divs - divs. */
4500
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
4501
{
4502
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4503
    if (unlikely(Rc(ctx->opcode) != 0))
4504
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4505
}
4506

    
4507
/* divso - divso. */
4508
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
4509
{
4510
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4511
    if (unlikely(Rc(ctx->opcode) != 0))
4512
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4513
}
4514

    
4515
/* doz - doz. */
4516
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
4517
{
4518
    int l1 = gen_new_label();
4519
    int l2 = gen_new_label();
4520
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4521
    tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4522
    tcg_gen_br(l2);
4523
    gen_set_label(l1);
4524
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4525
    gen_set_label(l2);
4526
    if (unlikely(Rc(ctx->opcode) != 0))
4527
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4528
}
4529

    
4530
/* dozo - dozo. */
4531
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
4532
{
4533
    int l1 = gen_new_label();
4534
    int l2 = gen_new_label();
4535
    TCGv t0 = tcg_temp_new();
4536
    TCGv t1 = tcg_temp_new();
4537
    TCGv t2 = tcg_temp_new();
4538
    /* Start with XER OV disabled, the most likely case */
4539
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4540
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4541
    tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4542
    tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4543
    tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4544
    tcg_gen_andc_tl(t1, t1, t2);
4545
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4546
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4547
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4548
    tcg_gen_br(l2);
4549
    gen_set_label(l1);
4550
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4551
    gen_set_label(l2);
4552
    tcg_temp_free(t0);
4553
    tcg_temp_free(t1);
4554
    tcg_temp_free(t2);
4555
    if (unlikely(Rc(ctx->opcode) != 0))
4556
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4557
}
4558

    
4559
/* dozi */
4560
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4561
{
4562
    target_long simm = SIMM(ctx->opcode);
4563
    int l1 = gen_new_label();
4564
    int l2 = gen_new_label();
4565
    tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4566
    tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4567
    tcg_gen_br(l2);
4568
    gen_set_label(l1);
4569
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4570
    gen_set_label(l2);
4571
    if (unlikely(Rc(ctx->opcode) != 0))
4572
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4573
}
4574

    
4575
/* lscbx - lscbx. */
4576
GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
4577
{
4578
    TCGv t0 = tcg_temp_new();
4579
    TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4580
    TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4581
    TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
4582

    
4583
    gen_addr_reg_index(ctx, t0);
4584
    /* NIP cannot be restored if the memory exception comes from an helper */
4585
    gen_update_nip(ctx, ctx->nip - 4);
4586
    gen_helper_lscbx(t0, t0, t1, t2, t3);
4587
    tcg_temp_free_i32(t1);
4588
    tcg_temp_free_i32(t2);
4589
    tcg_temp_free_i32(t3);
4590
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4591
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4592
    if (unlikely(Rc(ctx->opcode) != 0))
4593
        gen_set_Rc0(ctx, t0);
4594
    tcg_temp_free(t0);
4595
}
4596

    
4597
/* maskg - maskg. */
4598
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
4599
{
4600
    int l1 = gen_new_label();
4601
    TCGv t0 = tcg_temp_new();
4602
    TCGv t1 = tcg_temp_new();
4603
    TCGv t2 = tcg_temp_new();
4604
    TCGv t3 = tcg_temp_new();
4605
    tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4606
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4607
    tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4608
    tcg_gen_addi_tl(t2, t0, 1);
4609
    tcg_gen_shr_tl(t2, t3, t2);
4610
    tcg_gen_shr_tl(t3, t3, t1);
4611
    tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4612
    tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4613
    tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4614
    gen_set_label(l1);
4615
    tcg_temp_free(t0);
4616
    tcg_temp_free(t1);
4617
    tcg_temp_free(t2);
4618
    tcg_temp_free(t3);
4619
    if (unlikely(Rc(ctx->opcode) != 0))
4620
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4621
}
4622

    
4623
/* maskir - maskir. */
4624
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
4625
{
4626
    TCGv t0 = tcg_temp_new();
4627
    TCGv t1 = tcg_temp_new();
4628
    tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4629
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4630
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4631
    tcg_temp_free(t0);
4632
    tcg_temp_free(t1);
4633
    if (unlikely(Rc(ctx->opcode) != 0))
4634
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4635
}
4636

    
4637
/* mul - mul. */
4638
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
4639
{
4640
    TCGv_i64 t0 = tcg_temp_new_i64();
4641
    TCGv_i64 t1 = tcg_temp_new_i64();
4642
    TCGv t2 = tcg_temp_new();
4643
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4644
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4645
    tcg_gen_mul_i64(t0, t0, t1);
4646
    tcg_gen_trunc_i64_tl(t2, t0);
4647
    gen_store_spr(SPR_MQ, t2);
4648
    tcg_gen_shri_i64(t1, t0, 32);
4649
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4650
    tcg_temp_free_i64(t0);
4651
    tcg_temp_free_i64(t1);
4652
    tcg_temp_free(t2);
4653
    if (unlikely(Rc(ctx->opcode) != 0))
4654
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4655
}
4656

    
4657
/* mulo - mulo. */
4658
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
4659
{
4660
    int l1 = gen_new_label();
4661
    TCGv_i64 t0 = tcg_temp_new_i64();
4662
    TCGv_i64 t1 = tcg_temp_new_i64();
4663
    TCGv t2 = tcg_temp_new();
4664
    /* Start with XER OV disabled, the most likely case */
4665
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4666
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4667
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4668
    tcg_gen_mul_i64(t0, t0, t1);
4669
    tcg_gen_trunc_i64_tl(t2, t0);
4670
    gen_store_spr(SPR_MQ, t2);
4671
    tcg_gen_shri_i64(t1, t0, 32);
4672
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4673
    tcg_gen_ext32s_i64(t1, t0);
4674
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4675
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4676
    gen_set_label(l1);
4677
    tcg_temp_free_i64(t0);
4678
    tcg_temp_free_i64(t1);
4679
    tcg_temp_free(t2);
4680
    if (unlikely(Rc(ctx->opcode) != 0))
4681
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4682
}
4683

    
4684
/* nabs - nabs. */
4685
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
4686
{
4687
    int l1 = gen_new_label();
4688
    int l2 = gen_new_label();
4689
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4690
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4691
    tcg_gen_br(l2);
4692
    gen_set_label(l1);
4693
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4694
    gen_set_label(l2);
4695
    if (unlikely(Rc(ctx->opcode) != 0))
4696
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4697
}
4698

    
4699
/* nabso - nabso. */
4700
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
4701
{
4702
    int l1 = gen_new_label();
4703
    int l2 = gen_new_label();
4704
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4705
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4706
    tcg_gen_br(l2);
4707
    gen_set_label(l1);
4708
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4709
    gen_set_label(l2);
4710
    /* nabs never overflows */
4711
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4712
    if (unlikely(Rc(ctx->opcode) != 0))
4713
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4714
}
4715

    
4716
/* rlmi - rlmi. */
4717
GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4718
{
4719
    uint32_t mb = MB(ctx->opcode);
4720
    uint32_t me = ME(ctx->opcode);
4721
    TCGv t0 = tcg_temp_new();
4722
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4723
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4724
    tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4725
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4726
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4727
    tcg_temp_free(t0);
4728
    if (unlikely(Rc(ctx->opcode) != 0))
4729
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4730
}
4731

    
4732
/* rrib - rrib. */
4733
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
4734
{
4735
    TCGv t0 = tcg_temp_new();
4736
    TCGv t1 = tcg_temp_new();
4737
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4738
    tcg_gen_movi_tl(t1, 0x80000000);
4739
    tcg_gen_shr_tl(t1, t1, t0);
4740
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4741
    tcg_gen_and_tl(t0, t0, t1);
4742
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4743
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4744
    tcg_temp_free(t0);
4745
    tcg_temp_free(t1);
4746
    if (unlikely(Rc(ctx->opcode) != 0))
4747
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4748
}
4749

    
4750
/* sle - sle. */
4751
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
4752
{
4753
    TCGv t0 = tcg_temp_new();
4754
    TCGv t1 = tcg_temp_new();
4755
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4756
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4757
    tcg_gen_subfi_tl(t1, 32, t1);
4758
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4759
    tcg_gen_or_tl(t1, t0, t1);
4760
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4761
    gen_store_spr(SPR_MQ, t1);
4762
    tcg_temp_free(t0);
4763
    tcg_temp_free(t1);
4764
    if (unlikely(Rc(ctx->opcode) != 0))
4765
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4766
}
4767

    
4768
/* sleq - sleq. */
4769
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
4770
{
4771
    TCGv t0 = tcg_temp_new();
4772
    TCGv t1 = tcg_temp_new();
4773
    TCGv t2 = tcg_temp_new();
4774
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4775
    tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4776
    tcg_gen_shl_tl(t2, t2, t0);
4777
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4778
    gen_load_spr(t1, SPR_MQ);
4779
    gen_store_spr(SPR_MQ, t0);
4780
    tcg_gen_and_tl(t0, t0, t2);
4781
    tcg_gen_andc_tl(t1, t1, t2);
4782
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4783
    tcg_temp_free(t0);
4784
    tcg_temp_free(t1);
4785
    tcg_temp_free(t2);
4786
    if (unlikely(Rc(ctx->opcode) != 0))
4787
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4788
}
4789

    
4790
/* sliq - sliq. */
4791
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
4792
{
4793
    int sh = SH(ctx->opcode);
4794
    TCGv t0 = tcg_temp_new();
4795
    TCGv t1 = tcg_temp_new();
4796
    tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4797
    tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4798
    tcg_gen_or_tl(t1, t0, t1);
4799
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4800
    gen_store_spr(SPR_MQ, t1);
4801
    tcg_temp_free(t0);
4802
    tcg_temp_free(t1);
4803
    if (unlikely(Rc(ctx->opcode) != 0))
4804
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4805
}
4806

    
4807
/* slliq - slliq. */
4808
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
4809
{
4810
    int sh = SH(ctx->opcode);
4811
    TCGv t0 = tcg_temp_new();
4812
    TCGv t1 = tcg_temp_new();
4813
    tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4814
    gen_load_spr(t1, SPR_MQ);
4815
    gen_store_spr(SPR_MQ, t0);
4816
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU << sh));
4817
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
4818
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4819
    tcg_temp_free(t0);
4820
    tcg_temp_free(t1);
4821
    if (unlikely(Rc(ctx->opcode) != 0))
4822
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4823
}
4824

    
4825
/* sllq - sllq. */
4826
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
4827
{
4828
    int l1 = gen_new_label();
4829
    int l2 = gen_new_label();
4830
    TCGv t0 = tcg_temp_local_new();
4831
    TCGv t1 = tcg_temp_local_new();
4832
    TCGv t2 = tcg_temp_local_new();
4833
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4834
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4835
    tcg_gen_shl_tl(t1, t1, t2);
4836
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4837
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4838
    gen_load_spr(t0, SPR_MQ);
4839
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4840
    tcg_gen_br(l2);
4841
    gen_set_label(l1);
4842
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4843
    gen_load_spr(t2, SPR_MQ);
4844
    tcg_gen_andc_tl(t1, t2, t1);
4845
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4846
    gen_set_label(l2);
4847
    tcg_temp_free(t0);
4848
    tcg_temp_free(t1);
4849
    tcg_temp_free(t2);
4850
    if (unlikely(Rc(ctx->opcode) != 0))
4851
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4852
}
4853

    
4854
/* slq - slq. */
4855
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
4856
{
4857
    int l1 = gen_new_label();
4858
    TCGv t0 = tcg_temp_new();
4859
    TCGv t1 = tcg_temp_new();
4860
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4861
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4862
    tcg_gen_subfi_tl(t1, 32, t1);
4863
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4864
    tcg_gen_or_tl(t1, t0, t1);
4865
    gen_store_spr(SPR_MQ, t1);
4866
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4867
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4868
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4869
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4870
    gen_set_label(l1);
4871
    tcg_temp_free(t0);
4872
    tcg_temp_free(t1);
4873
    if (unlikely(Rc(ctx->opcode) != 0))
4874
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4875
}
4876

    
4877
/* sraiq - sraiq. */
4878
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
4879
{
4880
    int sh = SH(ctx->opcode);
4881
    int l1 = gen_new_label();
4882
    TCGv t0 = tcg_temp_new();
4883
    TCGv t1 = tcg_temp_new();
4884
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4885
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4886
    tcg_gen_or_tl(t0, t0, t1);
4887
    gen_store_spr(SPR_MQ, t0);
4888
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4889
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4890
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4891
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4892
    gen_set_label(l1);
4893
    tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
4894
    tcg_temp_free(t0);
4895
    tcg_temp_free(t1);
4896
    if (unlikely(Rc(ctx->opcode) != 0))
4897
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4898
}
4899

    
4900
/* sraq - sraq. */
4901
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
4902
{
4903
    int l1 = gen_new_label();
4904
    int l2 = gen_new_label();
4905
    TCGv t0 = tcg_temp_new();
4906
    TCGv t1 = tcg_temp_local_new();
4907
    TCGv t2 = tcg_temp_local_new();
4908
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4909
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4910
    tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
4911
    tcg_gen_subfi_tl(t2, 32, t2);
4912
    tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
4913
    tcg_gen_or_tl(t0, t0, t2);
4914
    gen_store_spr(SPR_MQ, t0);
4915
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4916
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
4917
    tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
4918
    tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
4919
    gen_set_label(l1);
4920
    tcg_temp_free(t0);
4921
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4922
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4923
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4924
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4925
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4926
    gen_set_label(l2);
4927
    tcg_temp_free(t1);
4928
    tcg_temp_free(t2);
4929
    if (unlikely(Rc(ctx->opcode) != 0))
4930
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4931
}
4932

    
4933
/* sre - sre. */
4934
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
4935
{
4936
    TCGv t0 = tcg_temp_new();
4937
    TCGv t1 = tcg_temp_new();
4938
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4939
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4940
    tcg_gen_subfi_tl(t1, 32, t1);
4941
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4942
    tcg_gen_or_tl(t1, t0, t1);
4943
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4944
    gen_store_spr(SPR_MQ, t1);
4945
    tcg_temp_free(t0);
4946
    tcg_temp_free(t1);
4947
    if (unlikely(Rc(ctx->opcode) != 0))
4948
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4949
}
4950

    
4951
/* srea - srea. */
4952
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
4953
{
4954
    TCGv t0 = tcg_temp_new();
4955
    TCGv t1 = tcg_temp_new();
4956
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4957
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4958
    gen_store_spr(SPR_MQ, t0);
4959
    tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
4960
    tcg_temp_free(t0);
4961
    tcg_temp_free(t1);
4962
    if (unlikely(Rc(ctx->opcode) != 0))
4963
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4964
}
4965

    
4966
/* sreq */
4967
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
4968
{
4969
    TCGv t0 = tcg_temp_new();
4970
    TCGv t1 = tcg_temp_new();
4971
    TCGv t2 = tcg_temp_new();
4972
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4973
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4974
    tcg_gen_shr_tl(t1, t1, t0);
4975
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4976
    gen_load_spr(t2, SPR_MQ);
4977
    gen_store_spr(SPR_MQ, t0);
4978
    tcg_gen_and_tl(t0, t0, t1);
4979
    tcg_gen_andc_tl(t2, t2, t1);
4980
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4981
    tcg_temp_free(t0);
4982
    tcg_temp_free(t1);
4983
    tcg_temp_free(t2);
4984
    if (unlikely(Rc(ctx->opcode) != 0))
4985
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4986
}
4987

    
4988
/* sriq */
4989
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
4990
{
4991
    int sh = SH(ctx->opcode);
4992
    TCGv t0 = tcg_temp_new();
4993
    TCGv t1 = tcg_temp_new();
4994
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4995
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4996
    tcg_gen_or_tl(t1, t0, t1);
4997
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4998
    gen_store_spr(SPR_MQ, t1);
4999
    tcg_temp_free(t0);
5000
    tcg_temp_free(t1);
5001
    if (unlikely(Rc(ctx->opcode) != 0))
5002
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5003
}
5004

    
5005
/* srliq */
5006
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
5007
{
5008
    int sh = SH(ctx->opcode);
5009
    TCGv t0 = tcg_temp_new();
5010
    TCGv t1 = tcg_temp_new();
5011
    tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5012
    gen_load_spr(t1, SPR_MQ);
5013
    gen_store_spr(SPR_MQ, t0);
5014
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU >> sh));
5015
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
5016
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5017
    tcg_temp_free(t0);
5018
    tcg_temp_free(t1);
5019
    if (unlikely(Rc(ctx->opcode) != 0))
5020
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5021
}
5022

    
5023
/* srlq */
5024
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
5025
{
5026
    int l1 = gen_new_label();
5027
    int l2 = gen_new_label();
5028
    TCGv t0 = tcg_temp_local_new();
5029
    TCGv t1 = tcg_temp_local_new();
5030
    TCGv t2 = tcg_temp_local_new();
5031
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5032
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5033
    tcg_gen_shr_tl(t2, t1, t2);
5034
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5035
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5036
    gen_load_spr(t0, SPR_MQ);
5037
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5038
    tcg_gen_br(l2);
5039
    gen_set_label(l1);
5040
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5041
    tcg_gen_and_tl(t0, t0, t2);
5042
    gen_load_spr(t1, SPR_MQ);
5043
    tcg_gen_andc_tl(t1, t1, t2);
5044
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5045
    gen_set_label(l2);
5046
    tcg_temp_free(t0);
5047
    tcg_temp_free(t1);
5048
    tcg_temp_free(t2);
5049
    if (unlikely(Rc(ctx->opcode) != 0))
5050
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5051
}
5052

    
5053
/* srq */
5054
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
5055
{
5056
    int l1 = gen_new_label();
5057
    TCGv t0 = tcg_temp_new();
5058
    TCGv t1 = tcg_temp_new();
5059
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5060
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5061
    tcg_gen_subfi_tl(t1, 32, t1);
5062
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5063
    tcg_gen_or_tl(t1, t0, t1);
5064
    gen_store_spr(SPR_MQ, t1);
5065
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5066
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5067
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5068
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5069
    gen_set_label(l1);
5070
    tcg_temp_free(t0);
5071
    tcg_temp_free(t1);
5072
    if (unlikely(Rc(ctx->opcode) != 0))
5073
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5074
}
5075

    
5076
/* PowerPC 602 specific instructions */
5077
/* dsa  */
5078
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
5079
{
5080
    /* XXX: TODO */
5081
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5082
}
5083

    
5084
/* esa */
5085
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
5086
{
5087
    /* XXX: TODO */
5088
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5089
}
5090

    
5091
/* mfrom */
5092
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
5093
{
5094
#if defined(CONFIG_USER_ONLY)
5095
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5096
#else
5097
    if (unlikely(!ctx->mem_idx)) {
5098
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5099
        return;
5100
    }
5101
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5102
#endif
5103
}
5104

    
5105
/* 602 - 603 - G2 TLB management */
5106
/* tlbld */
5107
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
5108
{
5109
#if defined(CONFIG_USER_ONLY)
5110
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5111
#else
5112
    if (unlikely(!ctx->mem_idx)) {
5113
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5114
        return;
5115
    }
5116
    gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5117
#endif
5118
}
5119

    
5120
/* tlbli */
5121
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
5122
{
5123
#if defined(CONFIG_USER_ONLY)
5124
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5125
#else
5126
    if (unlikely(!ctx->mem_idx)) {
5127
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5128
        return;
5129
    }
5130
    gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5131
#endif
5132
}
5133

    
5134
/* 74xx TLB management */
5135
/* tlbld */
5136
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
5137
{
5138
#if defined(CONFIG_USER_ONLY)
5139
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5140
#else
5141
    if (unlikely(!ctx->mem_idx)) {
5142
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5143
        return;
5144
    }
5145
    gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5146
#endif
5147
}
5148

    
5149
/* tlbli */
5150
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
5151
{
5152
#if defined(CONFIG_USER_ONLY)
5153
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5154
#else
5155
    if (unlikely(!ctx->mem_idx)) {
5156
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5157
        return;
5158
    }
5159
    gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5160
#endif
5161
}
5162

    
5163
/* POWER instructions not in PowerPC 601 */
5164
/* clf */
5165
GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
5166
{
5167
    /* Cache line flush: implemented as no-op */
5168
}
5169

    
5170
/* cli */
5171
GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
5172
{
5173
    /* Cache line invalidate: privileged and treated as no-op */
5174
#if defined(CONFIG_USER_ONLY)
5175
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5176
#else
5177
    if (unlikely(!ctx->mem_idx)) {
5178
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5179
        return;
5180
    }
5181
#endif
5182
}
5183

    
5184
/* dclst */
5185
GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
5186
{
5187
    /* Data cache line store: treated as no-op */
5188
}
5189

    
5190
GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
5191
{
5192
#if defined(CONFIG_USER_ONLY)
5193
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5194
#else
5195
    int ra = rA(ctx->opcode);
5196
    int rd = rD(ctx->opcode);
5197
    TCGv t0;
5198
    if (unlikely(!ctx->mem_idx)) {
5199
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5200
        return;
5201
    }
5202
    t0 = tcg_temp_new();
5203
    gen_addr_reg_index(ctx, t0);
5204
    tcg_gen_shri_tl(t0, t0, 28);
5205
    tcg_gen_andi_tl(t0, t0, 0xF);
5206
    gen_helper_load_sr(cpu_gpr[rd], t0);
5207
    tcg_temp_free(t0);
5208
    if (ra != 0 && ra != rd)
5209
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5210
#endif
5211
}
5212

    
5213
GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
5214
{
5215
#if defined(CONFIG_USER_ONLY)
5216
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5217
#else
5218
    TCGv t0;
5219
    if (unlikely(!ctx->mem_idx)) {
5220
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5221
        return;
5222
    }
5223
    t0 = tcg_temp_new();
5224
    gen_addr_reg_index(ctx, t0);
5225
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
5226
    tcg_temp_free(t0);
5227
#endif
5228
}
5229

    
5230
GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
5231
{
5232
#if defined(CONFIG_USER_ONLY)
5233
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5234
#else
5235
    if (unlikely(!ctx->mem_idx)) {
5236
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5237
        return;
5238
    }
5239
    gen_helper_rfsvc();
5240
    gen_sync_exception(ctx);
5241
#endif
5242
}
5243

    
5244
/* svc is not implemented for now */
5245

    
5246
/* POWER2 specific instructions */
5247
/* Quad manipulation (load/store two floats at a time) */
5248

    
5249
/* lfq */
5250
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5251
{
5252
    int rd = rD(ctx->opcode);
5253
    TCGv t0;
5254
    gen_set_access_type(ctx, ACCESS_FLOAT);
5255
    t0 = tcg_temp_new();
5256
    gen_addr_imm_index(ctx, t0, 0);
5257
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5258
    gen_addr_add(ctx, t0, t0, 8);
5259
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5260
    tcg_temp_free(t0);
5261
}
5262

    
5263
/* lfqu */
5264
GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5265
{
5266
    int ra = rA(ctx->opcode);
5267
    int rd = rD(ctx->opcode);
5268
    TCGv t0, t1;
5269
    gen_set_access_type(ctx, ACCESS_FLOAT);
5270
    t0 = tcg_temp_new();
5271
    t1 = tcg_temp_new();
5272
    gen_addr_imm_index(ctx, t0, 0);
5273
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5274
    gen_addr_add(ctx, t1, t0, 8);
5275
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5276
    if (ra != 0)
5277
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5278
    tcg_temp_free(t0);
5279
    tcg_temp_free(t1);
5280
}
5281

    
5282
/* lfqux */
5283
GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
5284
{
5285
    int ra = rA(ctx->opcode);
5286
    int rd = rD(ctx->opcode);
5287
    gen_set_access_type(ctx, ACCESS_FLOAT);
5288
    TCGv t0, t1;
5289
    t0 = tcg_temp_new();
5290
    gen_addr_reg_index(ctx, t0);
5291
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5292
    t1 = tcg_temp_new();
5293
    gen_addr_add(ctx, t1, t0, 8);
5294
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5295
    tcg_temp_free(t1);
5296
    if (ra != 0)
5297
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5298
    tcg_temp_free(t0);
5299
}
5300

    
5301
/* lfqx */
5302
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
5303
{
5304
    int rd = rD(ctx->opcode);
5305
    TCGv t0;
5306
    gen_set_access_type(ctx, ACCESS_FLOAT);
5307
    t0 = tcg_temp_new();
5308
    gen_addr_reg_index(ctx, t0);
5309
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5310
    gen_addr_add(ctx, t0, t0, 8);
5311
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5312
    tcg_temp_free(t0);
5313
}
5314

    
5315
/* stfq */
5316
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5317
{
5318
    int rd = rD(ctx->opcode);
5319
    TCGv t0;
5320
    gen_set_access_type(ctx, ACCESS_FLOAT);
5321
    t0 = tcg_temp_new();
5322
    gen_addr_imm_index(ctx, t0, 0);
5323
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5324
    gen_addr_add(ctx, t0, t0, 8);
5325
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5326
    tcg_temp_free(t0);
5327
}
5328

    
5329
/* stfqu */
5330
GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5331
{
5332
    int ra = rA(ctx->opcode);
5333
    int rd = rD(ctx->opcode);
5334
    TCGv t0, t1;
5335
    gen_set_access_type(ctx, ACCESS_FLOAT);
5336
    t0 = tcg_temp_new();
5337
    gen_addr_imm_index(ctx, t0, 0);
5338
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5339
    t1 = tcg_temp_new();
5340
    gen_addr_add(ctx, t1, t0, 8);
5341
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5342
    tcg_temp_free(t1);
5343
    if (ra != 0)
5344
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5345
    tcg_temp_free(t0);
5346
}
5347

    
5348
/* stfqux */
5349
GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
5350
{
5351
    int ra = rA(ctx->opcode);
5352
    int rd = rD(ctx->opcode);
5353
    TCGv t0, t1;
5354
    gen_set_access_type(ctx, ACCESS_FLOAT);
5355
    t0 = tcg_temp_new();
5356
    gen_addr_reg_index(ctx, t0);
5357
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5358
    t1 = tcg_temp_new();
5359
    gen_addr_add(ctx, t1, t0, 8);
5360
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5361
    tcg_temp_free(t1);
5362
    if (ra != 0)
5363
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5364
    tcg_temp_free(t0);
5365
}
5366

    
5367
/* stfqx */
5368
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
5369
{
5370
    int rd = rD(ctx->opcode);
5371
    TCGv t0;
5372
    gen_set_access_type(ctx, ACCESS_FLOAT);
5373
    t0 = tcg_temp_new();
5374
    gen_addr_reg_index(ctx, t0);
5375
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5376
    gen_addr_add(ctx, t0, t0, 8);
5377
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5378
    tcg_temp_free(t0);
5379
}
5380

    
5381
/* BookE specific instructions */
5382
/* XXX: not implemented on 440 ? */
5383
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
5384
{
5385
    /* XXX: TODO */
5386
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5387
}
5388

    
5389
/* XXX: not implemented on 440 ? */
5390
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
5391
{
5392
#if defined(CONFIG_USER_ONLY)
5393
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5394
#else
5395
    TCGv t0;
5396
    if (unlikely(!ctx->mem_idx)) {
5397
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5398
        return;
5399
    }
5400
    t0 = tcg_temp_new();
5401
    gen_addr_reg_index(ctx, t0);
5402
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
5403
    tcg_temp_free(t0);
5404
#endif
5405
}
5406

    
5407
/* All 405 MAC instructions are translated here */
5408
static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5409
                                                int opc2, int opc3,
5410
                                                int ra, int rb, int rt, int Rc)
5411
{
5412
    TCGv t0, t1;
5413

    
5414
    t0 = tcg_temp_local_new();
5415
    t1 = tcg_temp_local_new();
5416

    
5417
    switch (opc3 & 0x0D) {
5418
    case 0x05:
5419
        /* macchw    - macchw.    - macchwo   - macchwo.   */
5420
        /* macchws   - macchws.   - macchwso  - macchwso.  */
5421
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
5422
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
5423
        /* mulchw - mulchw. */
5424
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5425
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5426
        tcg_gen_ext16s_tl(t1, t1);
5427
        break;
5428
    case 0x04:
5429
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
5430
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
5431
        /* mulchwu - mulchwu. */
5432
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5433
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5434
        tcg_gen_ext16u_tl(t1, t1);
5435
        break;
5436
    case 0x01:
5437
        /* machhw    - machhw.    - machhwo   - machhwo.   */
5438
        /* machhws   - machhws.   - machhwso  - machhwso.  */
5439
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
5440
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
5441
        /* mulhhw - mulhhw. */
5442
        tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5443
        tcg_gen_ext16s_tl(t0, t0);
5444
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5445
        tcg_gen_ext16s_tl(t1, t1);
5446
        break;
5447
    case 0x00:
5448
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
5449
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
5450
        /* mulhhwu - mulhhwu. */
5451
        tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5452
        tcg_gen_ext16u_tl(t0, t0);
5453
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5454
        tcg_gen_ext16u_tl(t1, t1);
5455
        break;
5456
    case 0x0D:
5457
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
5458
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
5459
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
5460
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
5461
        /* mullhw - mullhw. */
5462
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5463
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5464
        break;
5465
    case 0x0C:
5466
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
5467
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
5468
        /* mullhwu - mullhwu. */
5469
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5470
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5471
        break;
5472
    }
5473
    if (opc2 & 0x04) {
5474
        /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5475
        tcg_gen_mul_tl(t1, t0, t1);
5476
        if (opc2 & 0x02) {
5477
            /* nmultiply-and-accumulate (0x0E) */
5478
            tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5479
        } else {
5480
            /* multiply-and-accumulate (0x0C) */
5481
            tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5482
        }
5483

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

    
5488
            if (opc3 & 0x10) {
5489
                /* Start with XER OV disabled, the most likely case */
5490
                tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5491
            }
5492
            if (opc3 & 0x01) {
5493
                /* Signed */
5494
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5495
                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5496
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5497
                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
5498
                if (opc3 & 0x02) {
5499
                    /* Saturate */
5500
                    tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5501
                    tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5502
                }
5503
            } else {
5504
                /* Unsigned */
5505
                tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5506
                if (opc3 & 0x02) {
5507
                    /* Saturate */
5508
                    tcg_gen_movi_tl(t0, UINT32_MAX);
5509
                }
5510
            }
5511
            if (opc3 & 0x10) {
5512
                /* Check overflow */
5513
                tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5514
            }
5515
            gen_set_label(l1);
5516
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
5517
        }
5518
    } else {
5519
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5520
    }
5521
    tcg_temp_free(t0);
5522
    tcg_temp_free(t1);
5523
    if (unlikely(Rc) != 0) {
5524
        /* Update Rc0 */
5525
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5526
    }
5527
}
5528

    
5529
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
5530
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)                  \
5531
{                                                                             \
5532
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
5533
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
5534
}
5535

    
5536
/* macchw    - macchw.    */
5537
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5538
/* macchwo   - macchwo.   */
5539
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5540
/* macchws   - macchws.   */
5541
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5542
/* macchwso  - macchwso.  */
5543
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5544
/* macchwsu  - macchwsu.  */
5545
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5546
/* macchwsuo - macchwsuo. */
5547
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5548
/* macchwu   - macchwu.   */
5549
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5550
/* macchwuo  - macchwuo.  */
5551
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5552
/* machhw    - machhw.    */
5553
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5554
/* machhwo   - machhwo.   */
5555
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5556
/* machhws   - machhws.   */
5557
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5558
/* machhwso  - machhwso.  */
5559
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5560
/* machhwsu  - machhwsu.  */
5561
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5562
/* machhwsuo - machhwsuo. */
5563
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5564
/* machhwu   - machhwu.   */
5565
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5566
/* machhwuo  - machhwuo.  */
5567
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5568
/* maclhw    - maclhw.    */
5569
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5570
/* maclhwo   - maclhwo.   */
5571
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5572
/* maclhws   - maclhws.   */
5573
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5574
/* maclhwso  - maclhwso.  */
5575
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5576
/* maclhwu   - maclhwu.   */
5577
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5578
/* maclhwuo  - maclhwuo.  */
5579
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5580
/* maclhwsu  - maclhwsu.  */
5581
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5582
/* maclhwsuo - maclhwsuo. */
5583
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5584
/* nmacchw   - nmacchw.   */
5585
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5586
/* nmacchwo  - nmacchwo.  */
5587
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5588
/* nmacchws  - nmacchws.  */
5589
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5590
/* nmacchwso - nmacchwso. */
5591
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5592
/* nmachhw   - nmachhw.   */
5593
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5594
/* nmachhwo  - nmachhwo.  */
5595
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5596
/* nmachhws  - nmachhws.  */
5597
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5598
/* nmachhwso - nmachhwso. */
5599
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5600
/* nmaclhw   - nmaclhw.   */
5601
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5602
/* nmaclhwo  - nmaclhwo.  */
5603
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5604
/* nmaclhws  - nmaclhws.  */
5605
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5606
/* nmaclhwso - nmaclhwso. */
5607
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5608

    
5609
/* mulchw  - mulchw.  */
5610
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5611
/* mulchwu - mulchwu. */
5612
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5613
/* mulhhw  - mulhhw.  */
5614
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5615
/* mulhhwu - mulhhwu. */
5616
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5617
/* mullhw  - mullhw.  */
5618
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5619
/* mullhwu - mullhwu. */
5620
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5621

    
5622
/* mfdcr */
5623
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
5624
{
5625
#if defined(CONFIG_USER_ONLY)
5626
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5627
#else
5628
    TCGv dcrn;
5629
    if (unlikely(!ctx->mem_idx)) {
5630
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5631
        return;
5632
    }
5633
    /* NIP cannot be restored if the memory exception comes from an helper */
5634
    gen_update_nip(ctx, ctx->nip - 4);
5635
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5636
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
5637
    tcg_temp_free(dcrn);
5638
#endif
5639
}
5640

    
5641
/* mtdcr */
5642
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
5643
{
5644
#if defined(CONFIG_USER_ONLY)
5645
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5646
#else
5647
    TCGv dcrn;
5648
    if (unlikely(!ctx->mem_idx)) {
5649
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5650
        return;
5651
    }
5652
    /* NIP cannot be restored if the memory exception comes from an helper */
5653
    gen_update_nip(ctx, ctx->nip - 4);
5654
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5655
    gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
5656
    tcg_temp_free(dcrn);
5657
#endif
5658
}
5659

    
5660
/* mfdcrx */
5661
/* XXX: not implemented on 440 ? */
5662
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
5663
{
5664
#if defined(CONFIG_USER_ONLY)
5665
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5666
#else
5667
    if (unlikely(!ctx->mem_idx)) {
5668
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5669
        return;
5670
    }
5671
    /* NIP cannot be restored if the memory exception comes from an helper */
5672
    gen_update_nip(ctx, ctx->nip - 4);
5673
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5674
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5675
#endif
5676
}
5677

    
5678
/* mtdcrx */
5679
/* XXX: not implemented on 440 ? */
5680
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
5681
{
5682
#if defined(CONFIG_USER_ONLY)
5683
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5684
#else
5685
    if (unlikely(!ctx->mem_idx)) {
5686
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
5687
        return;
5688
    }
5689
    /* NIP cannot be restored if the memory exception comes from an helper */
5690
    gen_update_nip(ctx, ctx->nip - 4);
5691
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5692
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5693
#endif
5694
}
5695

    
5696
/* mfdcrux (PPC 460) : user-mode access to DCR */
5697
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
5698
{
5699
    /* NIP cannot be restored if the memory exception comes from an helper */
5700
    gen_update_nip(ctx, ctx->nip - 4);
5701
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5702
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5703
}
5704

    
5705
/* mtdcrux (PPC 460) : user-mode access to DCR */
5706
GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
5707
{
5708
    /* NIP cannot be restored if the memory exception comes from an helper */
5709
    gen_update_nip(ctx, ctx->nip - 4);
5710
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5711
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5712
}
5713

    
5714
/* dccci */
5715
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
5716
{
5717
#if defined(CONFIG_USER_ONLY)
5718
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5719
#else
5720
    if (unlikely(!ctx->mem_idx)) {
5721
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5722
        return;
5723
    }
5724
    /* interpreted as no-op */
5725
#endif
5726
}
5727

    
5728
/* dcread */
5729
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
5730
{
5731
#if defined(CONFIG_USER_ONLY)
5732
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5733
#else
5734
    TCGv EA, val;
5735
    if (unlikely(!ctx->mem_idx)) {
5736
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5737
        return;
5738
    }
5739
    gen_set_access_type(ctx, ACCESS_CACHE);
5740
    EA = tcg_temp_new();
5741
    gen_addr_reg_index(ctx, EA);
5742
    val = tcg_temp_new();
5743
    gen_qemu_ld32u(ctx, val, EA);
5744
    tcg_temp_free(val);
5745
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5746
    tcg_temp_free(EA);
5747
#endif
5748
}
5749

    
5750
/* icbt */
5751
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
5752
{
5753
    /* interpreted as no-op */
5754
    /* XXX: specification say this is treated as a load by the MMU
5755
     *      but does not generate any exception
5756
     */
5757
}
5758

    
5759
/* iccci */
5760
GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
5761
{
5762
#if defined(CONFIG_USER_ONLY)
5763
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5764
#else
5765
    if (unlikely(!ctx->mem_idx)) {
5766
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5767
        return;
5768
    }
5769
    /* interpreted as no-op */
5770
#endif
5771
}
5772

    
5773
/* icread */
5774
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
5775
{
5776
#if defined(CONFIG_USER_ONLY)
5777
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5778
#else
5779
    if (unlikely(!ctx->mem_idx)) {
5780
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5781
        return;
5782
    }
5783
    /* interpreted as no-op */
5784
#endif
5785
}
5786

    
5787
/* rfci (mem_idx only) */
5788
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
5789
{
5790
#if defined(CONFIG_USER_ONLY)
5791
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5792
#else
5793
    if (unlikely(!ctx->mem_idx)) {
5794
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5795
        return;
5796
    }
5797
    /* Restore CPU state */
5798
    gen_helper_40x_rfci();
5799
    gen_sync_exception(ctx);
5800
#endif
5801
}
5802

    
5803
GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
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
    /* Restore CPU state */
5813
    gen_helper_rfci();
5814
    gen_sync_exception(ctx);
5815
#endif
5816
}
5817

    
5818
/* BookE specific */
5819
/* XXX: not implemented on 440 ? */
5820
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
5821
{
5822
#if defined(CONFIG_USER_ONLY)
5823
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5824
#else
5825
    if (unlikely(!ctx->mem_idx)) {
5826
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5827
        return;
5828
    }
5829
    /* Restore CPU state */
5830
    gen_helper_rfdi();
5831
    gen_sync_exception(ctx);
5832
#endif
5833
}
5834

    
5835
/* XXX: not implemented on 440 ? */
5836
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
5837
{
5838
#if defined(CONFIG_USER_ONLY)
5839
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5840
#else
5841
    if (unlikely(!ctx->mem_idx)) {
5842
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5843
        return;
5844
    }
5845
    /* Restore CPU state */
5846
    gen_helper_rfmci();
5847
    gen_sync_exception(ctx);
5848
#endif
5849
}
5850

    
5851
/* TLB management - PowerPC 405 implementation */
5852
/* tlbre */
5853
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
5854
{
5855
#if defined(CONFIG_USER_ONLY)
5856
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5857
#else
5858
    if (unlikely(!ctx->mem_idx)) {
5859
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5860
        return;
5861
    }
5862
    switch (rB(ctx->opcode)) {
5863
    case 0:
5864
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5865
        break;
5866
    case 1:
5867
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5868
        break;
5869
    default:
5870
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5871
        break;
5872
    }
5873
#endif
5874
}
5875

    
5876
/* tlbsx - tlbsx. */
5877
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5878
{
5879
#if defined(CONFIG_USER_ONLY)
5880
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5881
#else
5882
    TCGv t0;
5883
    if (unlikely(!ctx->mem_idx)) {
5884
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5885
        return;
5886
    }
5887
    t0 = tcg_temp_new();
5888
    gen_addr_reg_index(ctx, t0);
5889
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5890
    tcg_temp_free(t0);
5891
    if (Rc(ctx->opcode)) {
5892
        int l1 = gen_new_label();
5893
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5894
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5895
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5896
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5897
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5898
        gen_set_label(l1);
5899
    }
5900
#endif
5901
}
5902

    
5903
/* tlbwe */
5904
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
5905
{
5906
#if defined(CONFIG_USER_ONLY)
5907
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5908
#else
5909
    if (unlikely(!ctx->mem_idx)) {
5910
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5911
        return;
5912
    }
5913
    switch (rB(ctx->opcode)) {
5914
    case 0:
5915
        gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5916
        break;
5917
    case 1:
5918
        gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5919
        break;
5920
    default:
5921
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5922
        break;
5923
    }
5924
#endif
5925
}
5926

    
5927
/* TLB management - PowerPC 440 implementation */
5928
/* tlbre */
5929
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5930
{
5931
#if defined(CONFIG_USER_ONLY)
5932
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5933
#else
5934
    if (unlikely(!ctx->mem_idx)) {
5935
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5936
        return;
5937
    }
5938
    switch (rB(ctx->opcode)) {
5939
    case 0:
5940
    case 1:
5941
    case 2:
5942
        {
5943
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5944
            gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5945
            tcg_temp_free_i32(t0);
5946
        }
5947
        break;
5948
    default:
5949
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5950
        break;
5951
    }
5952
#endif
5953
}
5954

    
5955
/* tlbsx - tlbsx. */
5956
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5957
{
5958
#if defined(CONFIG_USER_ONLY)
5959
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5960
#else
5961
    TCGv t0;
5962
    if (unlikely(!ctx->mem_idx)) {
5963
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5964
        return;
5965
    }
5966
    t0 = tcg_temp_new();
5967
    gen_addr_reg_index(ctx, t0);
5968
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5969
    tcg_temp_free(t0);
5970
    if (Rc(ctx->opcode)) {
5971
        int l1 = gen_new_label();
5972
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5973
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5974
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5975
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5976
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5977
        gen_set_label(l1);
5978
    }
5979
#endif
5980
}
5981

    
5982
/* tlbwe */
5983
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5984
{
5985
#if defined(CONFIG_USER_ONLY)
5986
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5987
#else
5988
    if (unlikely(!ctx->mem_idx)) {
5989
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5990
        return;
5991
    }
5992
    switch (rB(ctx->opcode)) {
5993
    case 0:
5994
    case 1:
5995
    case 2:
5996
        {
5997
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5998
            gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5999
            tcg_temp_free_i32(t0);
6000
        }
6001
        break;
6002
    default:
6003
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6004
        break;
6005
    }
6006
#endif
6007
}
6008

    
6009
/* wrtee */
6010
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
6011
{
6012
#if defined(CONFIG_USER_ONLY)
6013
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6014
#else
6015
    TCGv t0;
6016
    if (unlikely(!ctx->mem_idx)) {
6017
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6018
        return;
6019
    }
6020
    t0 = tcg_temp_new();
6021
    tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6022
    tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6023
    tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6024
    tcg_temp_free(t0);
6025
    /* Stop translation to have a chance to raise an exception
6026
     * if we just set msr_ee to 1
6027
     */
6028
    gen_stop_exception(ctx);
6029
#endif
6030
}
6031

    
6032
/* wrteei */
6033
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
6034
{
6035
#if defined(CONFIG_USER_ONLY)
6036
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6037
#else
6038
    if (unlikely(!ctx->mem_idx)) {
6039
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6040
        return;
6041
    }
6042
    if (ctx->opcode & 0x00010000) {
6043
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6044
        /* Stop translation to have a chance to raise an exception */
6045
        gen_stop_exception(ctx);
6046
    } else {
6047
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6048
    }
6049
#endif
6050
}
6051

    
6052
/* PowerPC 440 specific instructions */
6053
/* dlmzb */
6054
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
6055
{
6056
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6057
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
6058
                     cpu_gpr[rB(ctx->opcode)], t0);
6059
    tcg_temp_free_i32(t0);
6060
}
6061

    
6062
/* mbar replaces eieio on 440 */
6063
GEN_HANDLER(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, PPC_BOOKE)
6064
{
6065
    /* interpreted as no-op */
6066
}
6067

    
6068
/* msync replaces sync on 440 */
6069
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
6070
{
6071
    /* interpreted as no-op */
6072
}
6073

    
6074
/* icbt */
6075
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
6076
{
6077
    /* interpreted as no-op */
6078
    /* XXX: specification say this is treated as a load by the MMU
6079
     *      but does not generate any exception
6080
     */
6081
}
6082

    
6083
/***                      Altivec vector extension                         ***/
6084
/* Altivec registers moves */
6085

    
6086
static always_inline TCGv_ptr gen_avr_ptr(int reg)
6087
{
6088
    TCGv_ptr r = tcg_temp_new_ptr();
6089
    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
6090
    return r;
6091
}
6092

    
6093
#define GEN_VR_LDX(name, opc2, opc3)                                          \
6094
GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)                  \
6095
{                                                                             \
6096
    TCGv EA;                                                                  \
6097
    if (unlikely(!ctx->altivec_enabled)) {                                    \
6098
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6099
        return;                                                               \
6100
    }                                                                         \
6101
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6102
    EA = tcg_temp_new();                                                      \
6103
    gen_addr_reg_index(ctx, EA);                                              \
6104
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6105
    if (ctx->le_mode) {                                                       \
6106
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6107
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6108
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6109
    } else {                                                                  \
6110
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6111
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6112
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6113
    }                                                                         \
6114
    tcg_temp_free(EA);                                                        \
6115
}
6116

    
6117
#define GEN_VR_STX(name, opc2, opc3)                                          \
6118
GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)              \
6119
{                                                                             \
6120
    TCGv EA;                                                                  \
6121
    if (unlikely(!ctx->altivec_enabled)) {                                    \
6122
        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
6123
        return;                                                               \
6124
    }                                                                         \
6125
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6126
    EA = tcg_temp_new();                                                      \
6127
    gen_addr_reg_index(ctx, EA);                                              \
6128
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6129
    if (ctx->le_mode) {                                                       \
6130
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6131
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6132
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6133
    } else {                                                                  \
6134
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6135
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6136
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6137
    }                                                                         \
6138
    tcg_temp_free(EA);                                                        \
6139
}
6140

    
6141
#define GEN_VR_LVE(name, opc2, opc3)                                    \
6142
    GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)   \
6143
    {                                                                   \
6144
        TCGv EA;                                                        \
6145
        TCGv_ptr rs;                                                    \
6146
        if (unlikely(!ctx->altivec_enabled)) {                          \
6147
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6148
            return;                                                     \
6149
        }                                                               \
6150
        gen_set_access_type(ctx, ACCESS_INT);                           \
6151
        EA = tcg_temp_new();                                            \
6152
        gen_addr_reg_index(ctx, EA);                                    \
6153
        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6154
        gen_helper_lve##name (rs, EA);                                  \
6155
        tcg_temp_free(EA);                                              \
6156
        tcg_temp_free_ptr(rs);                                          \
6157
    }
6158

    
6159
#define GEN_VR_STVE(name, opc2, opc3)                                   \
6160
    GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)  \
6161
    {                                                                   \
6162
        TCGv EA;                                                        \
6163
        TCGv_ptr rs;                                                    \
6164
        if (unlikely(!ctx->altivec_enabled)) {                          \
6165
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6166
            return;                                                     \
6167
        }                                                               \
6168
        gen_set_access_type(ctx, ACCESS_INT);                           \
6169
        EA = tcg_temp_new();                                            \
6170
        gen_addr_reg_index(ctx, EA);                                    \
6171
        rs = gen_avr_ptr(rS(ctx->opcode));                              \
6172
        gen_helper_stve##name (rs, EA);                                 \
6173
        tcg_temp_free(EA);                                              \
6174
        tcg_temp_free_ptr(rs);                                          \
6175
    }
6176

    
6177
GEN_VR_LDX(lvx, 0x07, 0x03);
6178
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6179
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6180

    
6181
GEN_VR_LVE(bx, 0x07, 0x00);
6182
GEN_VR_LVE(hx, 0x07, 0x01);
6183
GEN_VR_LVE(wx, 0x07, 0x02);
6184

    
6185
GEN_VR_STX(svx, 0x07, 0x07);
6186
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6187
GEN_VR_STX(svxl, 0x07, 0x0F);
6188

    
6189
GEN_VR_STVE(bx, 0x07, 0x04);
6190
GEN_VR_STVE(hx, 0x07, 0x05);
6191
GEN_VR_STVE(wx, 0x07, 0x06);
6192

    
6193
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC)
6194
{
6195
    TCGv_ptr rd;
6196
    TCGv EA;
6197
    if (unlikely(!ctx->altivec_enabled)) {
6198
        gen_exception(ctx, POWERPC_EXCP_VPU);
6199
        return;
6200
    }
6201
    EA = tcg_temp_new();
6202
    gen_addr_reg_index(ctx, EA);
6203
    rd = gen_avr_ptr(rD(ctx->opcode));
6204
    gen_helper_lvsl(rd, EA);
6205
    tcg_temp_free(EA);
6206
    tcg_temp_free_ptr(rd);
6207
}
6208

    
6209
GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC)
6210
{
6211
    TCGv_ptr rd;
6212
    TCGv EA;
6213
    if (unlikely(!ctx->altivec_enabled)) {
6214
        gen_exception(ctx, POWERPC_EXCP_VPU);
6215
        return;
6216
    }
6217
    EA = tcg_temp_new();
6218
    gen_addr_reg_index(ctx, EA);
6219
    rd = gen_avr_ptr(rD(ctx->opcode));
6220
    gen_helper_lvsr(rd, EA);
6221
    tcg_temp_free(EA);
6222
    tcg_temp_free_ptr(rd);
6223
}
6224

    
6225
GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC)
6226
{
6227
    TCGv_i32 t;
6228
    if (unlikely(!ctx->altivec_enabled)) {
6229
        gen_exception(ctx, POWERPC_EXCP_VPU);
6230
        return;
6231
    }
6232
    tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
6233
    t = tcg_temp_new_i32();
6234
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, vscr));
6235
    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
6236
    tcg_temp_free_i32(t);
6237
}
6238

    
6239
GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC)
6240
{
6241
    TCGv_ptr p;
6242
    if (unlikely(!ctx->altivec_enabled)) {
6243
        gen_exception(ctx, POWERPC_EXCP_VPU);
6244
        return;
6245
    }
6246
    p = gen_avr_ptr(rD(ctx->opcode));
6247
    gen_helper_mtvscr(p);
6248
    tcg_temp_free_ptr(p);
6249
}
6250

    
6251
/* Logical operations */
6252
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
6253
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)            \
6254
{                                                                       \
6255
    if (unlikely(!ctx->altivec_enabled)) {                              \
6256
        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
6257
        return;                                                         \
6258
    }                                                                   \
6259
    tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
6260
    tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
6261
}
6262

    
6263
GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
6264
GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
6265
GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
6266
GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
6267
GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
6268

    
6269
#define GEN_VXFORM(name, opc2, opc3)                                    \
6270
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)            \
6271
{                                                                       \
6272
    TCGv_ptr ra, rb, rd;                                                \
6273
    if (unlikely(!ctx->altivec_enabled)) {                              \
6274
        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
6275
        return;                                                         \
6276
    }                                                                   \
6277
    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
6278
    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
6279
    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
6280
    gen_helper_##name (rd, ra, rb);                                     \
6281
    tcg_temp_free_ptr(ra);                                              \
6282
    tcg_temp_free_ptr(rb);                                              \
6283
    tcg_temp_free_ptr(rd);                                              \
6284
}
6285

    
6286
GEN_VXFORM(vaddubm, 0, 0);
6287
GEN_VXFORM(vadduhm, 0, 1);
6288
GEN_VXFORM(vadduwm, 0, 2);
6289
GEN_VXFORM(vsububm, 0, 16);
6290
GEN_VXFORM(vsubuhm, 0, 17);
6291
GEN_VXFORM(vsubuwm, 0, 18);
6292
GEN_VXFORM(vmaxub, 1, 0);
6293
GEN_VXFORM(vmaxuh, 1, 1);
6294
GEN_VXFORM(vmaxuw, 1, 2);
6295
GEN_VXFORM(vmaxsb, 1, 4);
6296
GEN_VXFORM(vmaxsh, 1, 5);
6297
GEN_VXFORM(vmaxsw, 1, 6);
6298
GEN_VXFORM(vminub, 1, 8);
6299
GEN_VXFORM(vminuh, 1, 9);
6300
GEN_VXFORM(vminuw, 1, 10);
6301
GEN_VXFORM(vminsb, 1, 12);
6302
GEN_VXFORM(vminsh, 1, 13);
6303
GEN_VXFORM(vminsw, 1, 14);
6304
GEN_VXFORM(vavgub, 1, 16);
6305
GEN_VXFORM(vavguh, 1, 17);
6306
GEN_VXFORM(vavguw, 1, 18);
6307
GEN_VXFORM(vavgsb, 1, 20);
6308
GEN_VXFORM(vavgsh, 1, 21);
6309
GEN_VXFORM(vavgsw, 1, 22);
6310
GEN_VXFORM(vmrghb, 6, 0);
6311
GEN_VXFORM(vmrghh, 6, 1);
6312
GEN_VXFORM(vmrghw, 6, 2);
6313
GEN_VXFORM(vmrglb, 6, 4);
6314
GEN_VXFORM(vmrglh, 6, 5);
6315
GEN_VXFORM(vmrglw, 6, 6);
6316
GEN_VXFORM(vmuloub, 4, 0);
6317
GEN_VXFORM(vmulouh, 4, 1);
6318
GEN_VXFORM(vmulosb, 4, 4);
6319
GEN_VXFORM(vmulosh, 4, 5);
6320
GEN_VXFORM(vmuleub, 4, 8);
6321
GEN_VXFORM(vmuleuh, 4, 9);
6322
GEN_VXFORM(vmulesb, 4, 12);
6323
GEN_VXFORM(vmulesh, 4, 13);
6324
GEN_VXFORM(vslb, 2, 4);
6325
GEN_VXFORM(vslh, 2, 5);
6326
GEN_VXFORM(vslw, 2, 6);
6327
GEN_VXFORM(vsrb, 2, 8);
6328
GEN_VXFORM(vsrh, 2, 9);
6329
GEN_VXFORM(vsrw, 2, 10);
6330
GEN_VXFORM(vsrab, 2, 12);
6331
GEN_VXFORM(vsrah, 2, 13);
6332
GEN_VXFORM(vsraw, 2, 14);
6333
GEN_VXFORM(vslo, 6, 16);
6334
GEN_VXFORM(vsro, 6, 17);
6335
GEN_VXFORM(vaddcuw, 0, 6);
6336
GEN_VXFORM(vsubcuw, 0, 22);
6337
GEN_VXFORM(vaddubs, 0, 8);
6338
GEN_VXFORM(vadduhs, 0, 9);
6339
GEN_VXFORM(vadduws, 0, 10);
6340
GEN_VXFORM(vaddsbs, 0, 12);
6341
GEN_VXFORM(vaddshs, 0, 13);
6342
GEN_VXFORM(vaddsws, 0, 14);
6343
GEN_VXFORM(vsububs, 0, 24);
6344
GEN_VXFORM(vsubuhs, 0, 25);
6345
GEN_VXFORM(vsubuws, 0, 26);
6346
GEN_VXFORM(vsubsbs, 0, 28);
6347
GEN_VXFORM(vsubshs, 0, 29);
6348
GEN_VXFORM(vsubsws, 0, 30);
6349
GEN_VXFORM(vrlb, 2, 0);
6350
GEN_VXFORM(vrlh, 2, 1);
6351
GEN_VXFORM(vrlw, 2, 2);
6352
GEN_VXFORM(vsl, 2, 7);
6353
GEN_VXFORM(vsr, 2, 11);
6354
GEN_VXFORM(vpkuhum, 7, 0);
6355
GEN_VXFORM(vpkuwum, 7, 1);
6356
GEN_VXFORM(vpkuhus, 7, 2);
6357
GEN_VXFORM(vpkuwus, 7, 3);
6358
GEN_VXFORM(vpkshus, 7, 4);
6359
GEN_VXFORM(vpkswus, 7, 5);
6360
GEN_VXFORM(vpkshss, 7, 6);
6361
GEN_VXFORM(vpkswss, 7, 7);
6362
GEN_VXFORM(vpkpx, 7, 12);
6363
GEN_VXFORM(vsum4ubs, 4, 24);
6364
GEN_VXFORM(vsum4sbs, 4, 28);
6365
GEN_VXFORM(vsum4shs, 4, 25);
6366
GEN_VXFORM(vsum2sws, 4, 26);
6367
GEN_VXFORM(vsumsws, 4, 30);
6368
GEN_VXFORM(vaddfp, 5, 0);
6369
GEN_VXFORM(vsubfp, 5, 1);
6370
GEN_VXFORM(vmaxfp, 5, 16);
6371
GEN_VXFORM(vminfp, 5, 17);
6372

    
6373
#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
6374
    GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC)   \
6375
    {                                                                   \
6376
        TCGv_ptr ra, rb, rd;                                            \
6377
        if (unlikely(!ctx->altivec_enabled)) {                          \
6378
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6379
            return;                                                     \
6380
        }                                                               \
6381
        ra = gen_avr_ptr(rA(ctx->opcode));                              \
6382
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
6383
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6384
        gen_helper_##opname (rd, ra, rb);                               \
6385
        tcg_temp_free_ptr(ra);                                          \
6386
        tcg_temp_free_ptr(rb);                                          \
6387
        tcg_temp_free_ptr(rd);                                          \
6388
    }
6389

    
6390
#define GEN_VXRFORM(name, opc2, opc3)                                \
6391
    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
6392
    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
6393

    
6394
GEN_VXRFORM(vcmpequb, 3, 0)
6395
GEN_VXRFORM(vcmpequh, 3, 1)
6396
GEN_VXRFORM(vcmpequw, 3, 2)
6397
GEN_VXRFORM(vcmpgtsb, 3, 12)
6398
GEN_VXRFORM(vcmpgtsh, 3, 13)
6399
GEN_VXRFORM(vcmpgtsw, 3, 14)
6400
GEN_VXRFORM(vcmpgtub, 3, 8)
6401
GEN_VXRFORM(vcmpgtuh, 3, 9)
6402
GEN_VXRFORM(vcmpgtuw, 3, 10)
6403
GEN_VXRFORM(vcmpeqfp, 3, 3)
6404
GEN_VXRFORM(vcmpgefp, 3, 7)
6405
GEN_VXRFORM(vcmpgtfp, 3, 11)
6406
GEN_VXRFORM(vcmpbfp, 3, 15)
6407

    
6408
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
6409
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)        \
6410
    {                                                                   \
6411
        TCGv_ptr rd;                                                    \
6412
        TCGv_i32 simm;                                                  \
6413
        if (unlikely(!ctx->altivec_enabled)) {                          \
6414
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6415
            return;                                                     \
6416
        }                                                               \
6417
        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
6418
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6419
        gen_helper_##name (rd, simm);                                   \
6420
        tcg_temp_free_i32(simm);                                        \
6421
        tcg_temp_free_ptr(rd);                                          \
6422
    }
6423

    
6424
GEN_VXFORM_SIMM(vspltisb, 6, 12);
6425
GEN_VXFORM_SIMM(vspltish, 6, 13);
6426
GEN_VXFORM_SIMM(vspltisw, 6, 14);
6427

    
6428
#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
6429
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)        \
6430
    {                                                                   \
6431
        TCGv_ptr rb, rd;                                                \
6432
        if (unlikely(!ctx->altivec_enabled)) {                          \
6433
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6434
            return;                                                     \
6435
        }                                                               \
6436
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
6437
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6438
        gen_helper_##name (rd, rb);                                     \
6439
        tcg_temp_free_ptr(rb);                                          \
6440
        tcg_temp_free_ptr(rd);                                         \
6441
    }
6442

    
6443
GEN_VXFORM_NOA(vupkhsb, 7, 8);
6444
GEN_VXFORM_NOA(vupkhsh, 7, 9);
6445
GEN_VXFORM_NOA(vupklsb, 7, 10);
6446
GEN_VXFORM_NOA(vupklsh, 7, 11);
6447
GEN_VXFORM_NOA(vupkhpx, 7, 13);
6448
GEN_VXFORM_NOA(vupklpx, 7, 15);
6449
GEN_VXFORM_NOA(vrefp, 5, 4);
6450
GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
6451
GEN_VXFORM_NOA(vlogefp, 5, 7);
6452
GEN_VXFORM_NOA(vrfim, 5, 8);
6453
GEN_VXFORM_NOA(vrfin, 5, 9);
6454
GEN_VXFORM_NOA(vrfip, 5, 10);
6455
GEN_VXFORM_NOA(vrfiz, 5, 11);
6456

    
6457
#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
6458
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)        \
6459
    {                                                                   \
6460
        TCGv_ptr rd;                                                    \
6461
        TCGv_i32 simm;                                                  \
6462
        if (unlikely(!ctx->altivec_enabled)) {                          \
6463
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6464
            return;                                                     \
6465
        }                                                               \
6466
        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
6467
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6468
        gen_helper_##name (rd, simm);                                   \
6469
        tcg_temp_free_i32(simm);                                        \
6470
        tcg_temp_free_ptr(rd);                                          \
6471
    }
6472

    
6473
#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
6474
    GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)        \
6475
    {                                                                   \
6476
        TCGv_ptr rb, rd;                                                \
6477
        TCGv_i32 uimm;                                                  \
6478
        if (unlikely(!ctx->altivec_enabled)) {                          \
6479
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6480
            return;                                                     \
6481
        }                                                               \
6482
        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
6483
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
6484
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6485
        gen_helper_##name (rd, rb, uimm);                               \
6486
        tcg_temp_free_i32(uimm);                                        \
6487
        tcg_temp_free_ptr(rb);                                          \
6488
        tcg_temp_free_ptr(rd);                                          \
6489
    }
6490

    
6491
GEN_VXFORM_UIMM(vspltb, 6, 8);
6492
GEN_VXFORM_UIMM(vsplth, 6, 9);
6493
GEN_VXFORM_UIMM(vspltw, 6, 10);
6494
GEN_VXFORM_UIMM(vcfux, 5, 12);
6495
GEN_VXFORM_UIMM(vcfsx, 5, 13);
6496
GEN_VXFORM_UIMM(vctuxs, 5, 14);
6497
GEN_VXFORM_UIMM(vctsxs, 5, 15);
6498

    
6499
GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC)
6500
{
6501
    TCGv_ptr ra, rb, rd;
6502
    TCGv_i32 sh;
6503
    if (unlikely(!ctx->altivec_enabled)) {
6504
        gen_exception(ctx, POWERPC_EXCP_VPU);
6505
        return;
6506
    }
6507
    ra = gen_avr_ptr(rA(ctx->opcode));
6508
    rb = gen_avr_ptr(rB(ctx->opcode));
6509
    rd = gen_avr_ptr(rD(ctx->opcode));
6510
    sh = tcg_const_i32(VSH(ctx->opcode));
6511
    gen_helper_vsldoi (rd, ra, rb, sh);
6512
    tcg_temp_free_ptr(ra);
6513
    tcg_temp_free_ptr(rb);
6514
    tcg_temp_free_ptr(rd);
6515
    tcg_temp_free_i32(sh);
6516
}
6517

    
6518
#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
6519
    GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC) \
6520
    {                                                                   \
6521
        TCGv_ptr ra, rb, rc, rd;                                        \
6522
        if (unlikely(!ctx->altivec_enabled)) {                          \
6523
            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
6524
            return;                                                     \
6525
        }                                                               \
6526
        ra = gen_avr_ptr(rA(ctx->opcode));                              \
6527
        rb = gen_avr_ptr(rB(ctx->opcode));                              \
6528
        rc = gen_avr_ptr(rC(ctx->opcode));                              \
6529
        rd = gen_avr_ptr(rD(ctx->opcode));                              \
6530
        if (Rc(ctx->opcode)) {                                          \
6531
            gen_helper_##name1 (rd, ra, rb, rc);                        \
6532
        } else {                                                        \
6533
            gen_helper_##name0 (rd, ra, rb, rc);                        \
6534
        }                                                               \
6535
        tcg_temp_free_ptr(ra);                                          \
6536
        tcg_temp_free_ptr(rb);                                          \
6537
        tcg_temp_free_ptr(rc);                                          \
6538
        tcg_temp_free_ptr(rd);                                          \
6539
    }
6540

    
6541
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
6542

    
6543
GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC)
6544
{
6545
    TCGv_ptr ra, rb, rc, rd;
6546
    if (unlikely(!ctx->altivec_enabled)) {
6547
        gen_exception(ctx, POWERPC_EXCP_VPU);
6548
        return;
6549
    }
6550
    ra = gen_avr_ptr(rA(ctx->opcode));
6551
    rb = gen_avr_ptr(rB(ctx->opcode));
6552
    rc = gen_avr_ptr(rC(ctx->opcode));
6553
    rd = gen_avr_ptr(rD(ctx->opcode));
6554
    gen_helper_vmladduhm(rd, ra, rb, rc);
6555
    tcg_temp_free_ptr(ra);
6556
    tcg_temp_free_ptr(rb);
6557
    tcg_temp_free_ptr(rc);
6558
    tcg_temp_free_ptr(rd);
6559
}
6560

    
6561
GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
6562
GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
6563
GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
6564
GEN_VAFORM_PAIRED(vsel, vperm, 21)
6565
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
6566

    
6567
/***                           SPE extension                               ***/
6568
/* Register moves */
6569

    
6570
static always_inline void gen_load_gpr64(TCGv_i64 t, int reg) {
6571
#if defined(TARGET_PPC64)
6572
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
6573
#else
6574
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6575
#endif
6576
}
6577

    
6578
static always_inline void gen_store_gpr64(int reg, TCGv_i64 t) {
6579
#if defined(TARGET_PPC64)
6580
    tcg_gen_mov_i64(cpu_gpr[reg], t);
6581
#else
6582
    TCGv_i64 tmp = tcg_temp_new_i64();
6583
    tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
6584
    tcg_gen_shri_i64(tmp, t, 32);
6585
    tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
6586
    tcg_temp_free_i64(tmp);
6587
#endif
6588
}
6589

    
6590
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
6591
GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)                   \
6592
{                                                                             \
6593
    if (Rc(ctx->opcode))                                                      \
6594
        gen_##name1(ctx);                                                     \
6595
    else                                                                      \
6596
        gen_##name0(ctx);                                                     \
6597
}
6598

    
6599
/* Handler for undefined SPE opcodes */
6600
static always_inline void gen_speundef (DisasContext *ctx)
6601
{
6602
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6603
}
6604

    
6605
/* SPE logic */
6606
#if defined(TARGET_PPC64)
6607
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
6608
static always_inline void gen_##name (DisasContext *ctx)                      \
6609
{                                                                             \
6610
    if (unlikely(!ctx->spe_enabled)) {                                        \
6611
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6612
        return;                                                               \
6613
    }                                                                         \
6614
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
6615
           cpu_gpr[rB(ctx->opcode)]);                                         \
6616
}
6617
#else
6618
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
6619
static always_inline void gen_##name (DisasContext *ctx)                      \
6620
{                                                                             \
6621
    if (unlikely(!ctx->spe_enabled)) {                                        \
6622
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6623
        return;                                                               \
6624
    }                                                                         \
6625
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
6626
           cpu_gpr[rB(ctx->opcode)]);                                         \
6627
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
6628
           cpu_gprh[rB(ctx->opcode)]);                                        \
6629
}
6630
#endif
6631

    
6632
GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6633
GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6634
GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6635
GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6636
GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6637
GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6638
GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6639
GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
6640

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

    
6682
/* SPE arithmetic */
6683
#if defined(TARGET_PPC64)
6684
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6685
static always_inline void gen_##name (DisasContext *ctx)                      \
6686
{                                                                             \
6687
    if (unlikely(!ctx->spe_enabled)) {                                        \
6688
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6689
        return;                                                               \
6690
    }                                                                         \
6691
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6692
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6693
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6694
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6695
    tcg_op(t0, t0);                                                           \
6696
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
6697
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6698
    tcg_temp_free_i64(t2);                                                    \
6699
    tcg_op(t1, t1);                                                           \
6700
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6701
    tcg_temp_free_i32(t0);                                                    \
6702
    tcg_temp_free_i32(t1);                                                    \
6703
}
6704
#else
6705
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6706
static always_inline void gen_##name (DisasContext *ctx)                      \
6707
{                                                                             \
6708
    if (unlikely(!ctx->spe_enabled)) {                                        \
6709
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6710
        return;                                                               \
6711
    }                                                                         \
6712
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);               \
6713
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);             \
6714
}
6715
#endif
6716

    
6717
static always_inline void gen_op_evabs (TCGv_i32 ret, TCGv_i32 arg1)
6718
{
6719
    int l1 = gen_new_label();
6720
    int l2 = gen_new_label();
6721

    
6722
    tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6723
    tcg_gen_neg_i32(ret, arg1);
6724
    tcg_gen_br(l2);
6725
    gen_set_label(l1);
6726
    tcg_gen_mov_i32(ret, arg1);
6727
    gen_set_label(l2);
6728
}
6729
GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6730
GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6731
GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6732
GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
6733
static always_inline void gen_op_evrndw (TCGv_i32 ret, TCGv_i32 arg1)
6734
{
6735
    tcg_gen_addi_i32(ret, arg1, 0x8000);
6736
    tcg_gen_ext16u_i32(ret, ret);
6737
}
6738
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
6739
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6740
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6741

    
6742
#if defined(TARGET_PPC64)
6743
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
6744
static always_inline void gen_##name (DisasContext *ctx)                      \
6745
{                                                                             \
6746
    if (unlikely(!ctx->spe_enabled)) {                                        \
6747
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6748
        return;                                                               \
6749
    }                                                                         \
6750
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6751
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6752
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
6753
    TCGv_i64 t3 = tcg_temp_local_new_i64();                                   \
6754
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6755
    tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]);                      \
6756
    tcg_op(t0, t0, t2);                                                       \
6757
    tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32);                       \
6758
    tcg_gen_trunc_i64_i32(t1, t3);                                            \
6759
    tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32);                       \
6760
    tcg_gen_trunc_i64_i32(t2, t3);                                            \
6761
    tcg_temp_free_i64(t3);                                                    \
6762
    tcg_op(t1, t1, t2);                                                       \
6763
    tcg_temp_free_i32(t2);                                                    \
6764
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6765
    tcg_temp_free_i32(t0);                                                    \
6766
    tcg_temp_free_i32(t1);                                                    \
6767
}
6768
#else
6769
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
6770
static always_inline void gen_##name (DisasContext *ctx)                      \
6771
{                                                                             \
6772
    if (unlikely(!ctx->spe_enabled)) {                                        \
6773
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6774
        return;                                                               \
6775
    }                                                                         \
6776
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
6777
           cpu_gpr[rB(ctx->opcode)]);                                         \
6778
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
6779
           cpu_gprh[rB(ctx->opcode)]);                                        \
6780
}
6781
#endif
6782

    
6783
static always_inline void gen_op_evsrwu (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6784
{
6785
    TCGv_i32 t0;
6786
    int l1, l2;
6787

    
6788
    l1 = gen_new_label();
6789
    l2 = gen_new_label();
6790
    t0 = tcg_temp_local_new_i32();
6791
    /* No error here: 6 bits are used */
6792
    tcg_gen_andi_i32(t0, arg2, 0x3F);
6793
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6794
    tcg_gen_shr_i32(ret, arg1, t0);
6795
    tcg_gen_br(l2);
6796
    gen_set_label(l1);
6797
    tcg_gen_movi_i32(ret, 0);
6798
    tcg_gen_br(l2);
6799
    tcg_temp_free_i32(t0);
6800
}
6801
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
6802
static always_inline void gen_op_evsrws (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6803
{
6804
    TCGv_i32 t0;
6805
    int l1, l2;
6806

    
6807
    l1 = gen_new_label();
6808
    l2 = gen_new_label();
6809
    t0 = tcg_temp_local_new_i32();
6810
    /* No error here: 6 bits are used */
6811
    tcg_gen_andi_i32(t0, arg2, 0x3F);
6812
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6813
    tcg_gen_sar_i32(ret, arg1, t0);
6814
    tcg_gen_br(l2);
6815
    gen_set_label(l1);
6816
    tcg_gen_movi_i32(ret, 0);
6817
    tcg_gen_br(l2);
6818
    tcg_temp_free_i32(t0);
6819
}
6820
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
6821
static always_inline void gen_op_evslw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6822
{
6823
    TCGv_i32 t0;
6824
    int l1, l2;
6825

    
6826
    l1 = gen_new_label();
6827
    l2 = gen_new_label();
6828
    t0 = tcg_temp_local_new_i32();
6829
    /* No error here: 6 bits are used */
6830
    tcg_gen_andi_i32(t0, arg2, 0x3F);
6831
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6832
    tcg_gen_shl_i32(ret, arg1, t0);
6833
    tcg_gen_br(l2);
6834
    gen_set_label(l1);
6835
    tcg_gen_movi_i32(ret, 0);
6836
    tcg_gen_br(l2);
6837
    tcg_temp_free_i32(t0);
6838
}
6839
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
6840
static always_inline void gen_op_evrlw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6841
{
6842
    TCGv_i32 t0 = tcg_temp_new_i32();
6843
    tcg_gen_andi_i32(t0, arg2, 0x1F);
6844
    tcg_gen_rotl_i32(ret, arg1, t0);
6845
    tcg_temp_free_i32(t0);
6846
}
6847
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
6848
static always_inline void gen_evmergehi (DisasContext *ctx)
6849
{
6850
    if (unlikely(!ctx->spe_enabled)) {
6851
        gen_exception(ctx, POWERPC_EXCP_APU);
6852
        return;
6853
    }
6854
#if defined(TARGET_PPC64)
6855
    TCGv t0 = tcg_temp_new();
6856
    TCGv t1 = tcg_temp_new();
6857
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6858
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6859
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6860
    tcg_temp_free(t0);
6861
    tcg_temp_free(t1);
6862
#else
6863
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6864
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6865
#endif
6866
}
6867
GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
6868
static always_inline void gen_op_evsubf (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6869
{
6870
    tcg_gen_sub_i32(ret, arg2, arg1);
6871
}
6872
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
6873

    
6874
/* SPE arithmetic immediate */
6875
#if defined(TARGET_PPC64)
6876
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
6877
static always_inline void gen_##name (DisasContext *ctx)                      \
6878
{                                                                             \
6879
    if (unlikely(!ctx->spe_enabled)) {                                        \
6880
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6881
        return;                                                               \
6882
    }                                                                         \
6883
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6884
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6885
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6886
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]);                      \
6887
    tcg_op(t0, t0, rA(ctx->opcode));                                          \
6888
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
6889
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6890
    tcg_temp_free_i64(t2);                                                    \
6891
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
6892
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6893
    tcg_temp_free_i32(t0);                                                    \
6894
    tcg_temp_free_i32(t1);                                                    \
6895
}
6896
#else
6897
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
6898
static always_inline void gen_##name (DisasContext *ctx)                      \
6899
{                                                                             \
6900
    if (unlikely(!ctx->spe_enabled)) {                                        \
6901
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6902
        return;                                                               \
6903
    }                                                                         \
6904
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],                \
6905
           rA(ctx->opcode));                                                  \
6906
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)],              \
6907
           rA(ctx->opcode));                                                  \
6908
}
6909
#endif
6910
GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
6911
GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
6912

    
6913
/* SPE comparison */
6914
#if defined(TARGET_PPC64)
6915
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
6916
static always_inline void gen_##name (DisasContext *ctx)                      \
6917
{                                                                             \
6918
    if (unlikely(!ctx->spe_enabled)) {                                        \
6919
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6920
        return;                                                               \
6921
    }                                                                         \
6922
    int l1 = gen_new_label();                                                 \
6923
    int l2 = gen_new_label();                                                 \
6924
    int l3 = gen_new_label();                                                 \
6925
    int l4 = gen_new_label();                                                 \
6926
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6927
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6928
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6929
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6930
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]);                      \
6931
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l1);                                 \
6932
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
6933
    tcg_gen_br(l2);                                                           \
6934
    gen_set_label(l1);                                                        \
6935
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
6936
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
6937
    gen_set_label(l2);                                                        \
6938
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
6939
    tcg_gen_trunc_i64_i32(t0, t2);                                            \
6940
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
6941
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6942
    tcg_temp_free_i64(t2);                                                    \
6943
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l3);                                 \
6944
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
6945
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
6946
    tcg_gen_br(l4);                                                           \
6947
    gen_set_label(l3);                                                        \
6948
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
6949
                    CRF_CH | CRF_CH_OR_CL);                                   \
6950
    gen_set_label(l4);                                                        \
6951
    tcg_temp_free_i32(t0);                                                    \
6952
    tcg_temp_free_i32(t1);                                                    \
6953
}
6954
#else
6955
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
6956
static always_inline void gen_##name (DisasContext *ctx)                      \
6957
{                                                                             \
6958
    if (unlikely(!ctx->spe_enabled)) {                                        \
6959
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
6960
        return;                                                               \
6961
    }                                                                         \
6962
    int l1 = gen_new_label();                                                 \
6963
    int l2 = gen_new_label();                                                 \
6964
    int l3 = gen_new_label();                                                 \
6965
    int l4 = gen_new_label();                                                 \
6966
                                                                              \
6967
    tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)],                    \
6968
                       cpu_gpr[rB(ctx->opcode)], l1);                         \
6969
    tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0);                           \
6970
    tcg_gen_br(l2);                                                           \
6971
    gen_set_label(l1);                                                        \
6972
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
6973
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
6974
    gen_set_label(l2);                                                        \
6975
    tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)],                   \
6976
                       cpu_gprh[rB(ctx->opcode)], l3);                        \
6977
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
6978
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
6979
    tcg_gen_br(l4);                                                           \
6980
    gen_set_label(l3);                                                        \
6981
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
6982
                    CRF_CH | CRF_CH_OR_CL);                                   \
6983
    gen_set_label(l4);                                                        \
6984
}
6985
#endif
6986
GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
6987
GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
6988
GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
6989
GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
6990
GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
6991

    
6992
/* SPE misc */
6993
static always_inline void gen_brinc (DisasContext *ctx)
6994
{
6995
    /* Note: brinc is usable even if SPE is disabled */
6996
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
6997
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6998
}
6999
static always_inline void gen_evmergelo (DisasContext *ctx)
7000
{
7001
    if (unlikely(!ctx->spe_enabled)) {
7002
        gen_exception(ctx, POWERPC_EXCP_APU);
7003
        return;
7004
    }
7005
#if defined(TARGET_PPC64)
7006
    TCGv t0 = tcg_temp_new();
7007
    TCGv t1 = tcg_temp_new();
7008
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
7009
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
7010
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7011
    tcg_temp_free(t0);
7012
    tcg_temp_free(t1);
7013
#else
7014
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7015
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7016
#endif
7017
}
7018
static always_inline void gen_evmergehilo (DisasContext *ctx)
7019
{
7020
    if (unlikely(!ctx->spe_enabled)) {
7021
        gen_exception(ctx, POWERPC_EXCP_APU);
7022
        return;
7023
    }
7024
#if defined(TARGET_PPC64)
7025
    TCGv t0 = tcg_temp_new();
7026
    TCGv t1 = tcg_temp_new();
7027
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
7028
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
7029
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7030
    tcg_temp_free(t0);
7031
    tcg_temp_free(t1);
7032
#else
7033
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7034
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7035
#endif
7036
}
7037
static always_inline void gen_evmergelohi (DisasContext *ctx)
7038
{
7039
    if (unlikely(!ctx->spe_enabled)) {
7040
        gen_exception(ctx, POWERPC_EXCP_APU);
7041
        return;
7042
    }
7043
#if defined(TARGET_PPC64)
7044
    TCGv t0 = tcg_temp_new();
7045
    TCGv t1 = tcg_temp_new();
7046
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
7047
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
7048
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7049
    tcg_temp_free(t0);
7050
    tcg_temp_free(t1);
7051
#else
7052
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7053
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7054
#endif
7055
}
7056
static always_inline void gen_evsplati (DisasContext *ctx)
7057
{
7058
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 11)) >> 27;
7059

    
7060
#if defined(TARGET_PPC64)
7061
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7062
#else
7063
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7064
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7065
#endif
7066
}
7067
static always_inline void gen_evsplatfi (DisasContext *ctx)
7068
{
7069
    uint64_t imm = rA(ctx->opcode) << 11;
7070

    
7071
#if defined(TARGET_PPC64)
7072
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
7073
#else
7074
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7075
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7076
#endif
7077
}
7078

    
7079
static always_inline void gen_evsel (DisasContext *ctx)
7080
{
7081
    int l1 = gen_new_label();
7082
    int l2 = gen_new_label();
7083
    int l3 = gen_new_label();
7084
    int l4 = gen_new_label();
7085
    TCGv_i32 t0 = tcg_temp_local_new_i32();
7086
#if defined(TARGET_PPC64)
7087
    TCGv t1 = tcg_temp_local_new();
7088
    TCGv t2 = tcg_temp_local_new();
7089
#endif
7090
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
7091
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
7092
#if defined(TARGET_PPC64)
7093
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7094
#else
7095
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7096
#endif
7097
    tcg_gen_br(l2);
7098
    gen_set_label(l1);
7099
#if defined(TARGET_PPC64)
7100
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7101
#else
7102
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7103
#endif
7104
    gen_set_label(l2);
7105
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
7106
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
7107
#if defined(TARGET_PPC64)
7108
    tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
7109
#else
7110
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7111
#endif
7112
    tcg_gen_br(l4);
7113
    gen_set_label(l3);
7114
#if defined(TARGET_PPC64)
7115
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
7116
#else
7117
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7118
#endif
7119
    gen_set_label(l4);
7120
    tcg_temp_free_i32(t0);
7121
#if defined(TARGET_PPC64)
7122
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
7123
    tcg_temp_free(t1);
7124
    tcg_temp_free(t2);
7125
#endif
7126
}
7127
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
7128
{
7129
    gen_evsel(ctx);
7130
}
7131
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
7132
{
7133
    gen_evsel(ctx);
7134
}
7135
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
7136
{
7137
    gen_evsel(ctx);
7138
}
7139
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
7140
{
7141
    gen_evsel(ctx);
7142
}
7143

    
7144
GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE); ////
7145
GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE);
7146
GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE); ////
7147
GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE);
7148
GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE); ////
7149
GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE); ////
7150
GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE); ////
7151
GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE); //
7152
GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE); ////
7153
GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE); ////
7154
GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE); ////
7155
GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE); ////
7156
GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE); ////
7157
GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE); ////
7158
GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE); ////
7159
GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE);
7160
GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE); ////
7161
GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE);
7162
GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE); //
7163
GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE);
7164
GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE); ////
7165
GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE); ////
7166
GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE); ////
7167
GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE); ////
7168
GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE); ////
7169

    
7170
/* SPE load and stores */
7171
static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, TCGv EA, int sh)
7172
{
7173
    target_ulong uimm = rB(ctx->opcode);
7174

    
7175
    if (rA(ctx->opcode) == 0) {
7176
        tcg_gen_movi_tl(EA, uimm << sh);
7177
    } else {
7178
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
7179
#if defined(TARGET_PPC64)
7180
        if (!ctx->sf_mode) {
7181
            tcg_gen_ext32u_tl(EA, EA);
7182
        }
7183
#endif
7184
    }
7185
}
7186

    
7187
static always_inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
7188
{
7189
#if defined(TARGET_PPC64)
7190
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7191
#else
7192
    TCGv_i64 t0 = tcg_temp_new_i64();
7193
    gen_qemu_ld64(ctx, t0, addr);
7194
    tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
7195
    tcg_gen_shri_i64(t0, t0, 32);
7196
    tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
7197
    tcg_temp_free_i64(t0);
7198
#endif
7199
}
7200

    
7201
static always_inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
7202
{
7203
#if defined(TARGET_PPC64)
7204
    TCGv t0 = tcg_temp_new();
7205
    gen_qemu_ld32u(ctx, t0, addr);
7206
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7207
    gen_addr_add(ctx, addr, addr, 4);
7208
    gen_qemu_ld32u(ctx, t0, addr);
7209
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7210
    tcg_temp_free(t0);
7211
#else
7212
    gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7213
    gen_addr_add(ctx, addr, addr, 4);
7214
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7215
#endif
7216
}
7217

    
7218
static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
7219
{
7220
    TCGv t0 = tcg_temp_new();
7221
#if defined(TARGET_PPC64)
7222
    gen_qemu_ld16u(ctx, t0, addr);
7223
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7224
    gen_addr_add(ctx, addr, addr, 2);
7225
    gen_qemu_ld16u(ctx, t0, addr);
7226
    tcg_gen_shli_tl(t0, t0, 32);
7227
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7228
    gen_addr_add(ctx, addr, addr, 2);
7229
    gen_qemu_ld16u(ctx, t0, addr);
7230
    tcg_gen_shli_tl(t0, t0, 16);
7231
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7232
    gen_addr_add(ctx, addr, addr, 2);
7233
    gen_qemu_ld16u(ctx, t0, addr);
7234
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7235
#else
7236
    gen_qemu_ld16u(ctx, t0, addr);
7237
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7238
    gen_addr_add(ctx, addr, addr, 2);
7239
    gen_qemu_ld16u(ctx, t0, addr);
7240
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7241
    gen_addr_add(ctx, addr, addr, 2);
7242
    gen_qemu_ld16u(ctx, t0, addr);
7243
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7244
    gen_addr_add(ctx, addr, addr, 2);
7245
    gen_qemu_ld16u(ctx, t0, addr);
7246
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7247
#endif
7248
    tcg_temp_free(t0);
7249
}
7250

    
7251
static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
7252
{
7253
    TCGv t0 = tcg_temp_new();
7254
    gen_qemu_ld16u(ctx, t0, addr);
7255
#if defined(TARGET_PPC64)
7256
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7257
    tcg_gen_shli_tl(t0, t0, 16);
7258
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7259
#else
7260
    tcg_gen_shli_tl(t0, t0, 16);
7261
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7262
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7263
#endif
7264
    tcg_temp_free(t0);
7265
}
7266

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

    
7281
static always_inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
7282
{
7283
    TCGv t0 = tcg_temp_new();
7284
    gen_qemu_ld16s(ctx, t0, addr);
7285
#if defined(TARGET_PPC64)
7286
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7287
    tcg_gen_ext32u_tl(t0, t0);
7288
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7289
#else
7290
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7291
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7292
#endif
7293
    tcg_temp_free(t0);
7294
}
7295

    
7296
static always_inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
7297
{
7298
    TCGv t0 = tcg_temp_new();
7299
#if defined(TARGET_PPC64)
7300
    gen_qemu_ld16u(ctx, t0, addr);
7301
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7302
    gen_addr_add(ctx, addr, addr, 2);
7303
    gen_qemu_ld16u(ctx, t0, addr);
7304
    tcg_gen_shli_tl(t0, t0, 16);
7305
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7306
#else
7307
    gen_qemu_ld16u(ctx, t0, addr);
7308
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7309
    gen_addr_add(ctx, addr, addr, 2);
7310
    gen_qemu_ld16u(ctx, t0, addr);
7311
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7312
#endif
7313
    tcg_temp_free(t0);
7314
}
7315

    
7316
static always_inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
7317
{
7318
#if defined(TARGET_PPC64)
7319
    TCGv t0 = tcg_temp_new();
7320
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7321
    gen_addr_add(ctx, addr, addr, 2);
7322
    gen_qemu_ld16u(ctx, t0, addr);
7323
    tcg_gen_shli_tl(t0, t0, 32);
7324
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7325
    tcg_temp_free(t0);
7326
#else
7327
    gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7328
    gen_addr_add(ctx, addr, addr, 2);
7329
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7330
#endif
7331
}
7332

    
7333
static always_inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
7334
{
7335
#if defined(TARGET_PPC64)
7336
    TCGv t0 = tcg_temp_new();
7337
    gen_qemu_ld16s(ctx, t0, addr);
7338
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
7339
    gen_addr_add(ctx, addr, addr, 2);
7340
    gen_qemu_ld16s(ctx, t0, addr);
7341
    tcg_gen_shli_tl(t0, t0, 32);
7342
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7343
    tcg_temp_free(t0);
7344
#else
7345
    gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7346
    gen_addr_add(ctx, addr, addr, 2);
7347
    gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7348
#endif
7349
}
7350

    
7351
static always_inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
7352
{
7353
    TCGv t0 = tcg_temp_new();
7354
    gen_qemu_ld32u(ctx, t0, addr);
7355
#if defined(TARGET_PPC64)
7356
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7357
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7358
#else
7359
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7360
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7361
#endif
7362
    tcg_temp_free(t0);
7363
}
7364

    
7365
static always_inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
7366
{
7367
    TCGv t0 = tcg_temp_new();
7368
#if defined(TARGET_PPC64)
7369
    gen_qemu_ld16u(ctx, t0, addr);
7370
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7371
    tcg_gen_shli_tl(t0, t0, 32);
7372
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7373
    gen_addr_add(ctx, addr, addr, 2);
7374
    gen_qemu_ld16u(ctx, t0, addr);
7375
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7376
    tcg_gen_shli_tl(t0, t0, 16);
7377
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7378
#else
7379
    gen_qemu_ld16u(ctx, t0, addr);
7380
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7381
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7382
    gen_addr_add(ctx, addr, addr, 2);
7383
    gen_qemu_ld16u(ctx, t0, addr);
7384
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7385
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
7386
#endif
7387
    tcg_temp_free(t0);
7388
}
7389

    
7390
static always_inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
7391
{
7392
#if defined(TARGET_PPC64)
7393
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7394
#else
7395
    TCGv_i64 t0 = tcg_temp_new_i64();
7396
    tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
7397
    gen_qemu_st64(ctx, t0, addr);
7398
    tcg_temp_free_i64(t0);
7399
#endif
7400
}
7401

    
7402
static always_inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
7403
{
7404
#if defined(TARGET_PPC64)
7405
    TCGv t0 = tcg_temp_new();
7406
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7407
    gen_qemu_st32(ctx, t0, addr);
7408
    tcg_temp_free(t0);
7409
#else
7410
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7411
#endif
7412
    gen_addr_add(ctx, addr, addr, 4);
7413
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7414
}
7415

    
7416
static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
7417
{
7418
    TCGv t0 = tcg_temp_new();
7419
#if defined(TARGET_PPC64)
7420
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7421
#else
7422
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7423
#endif
7424
    gen_qemu_st16(ctx, t0, addr);
7425
    gen_addr_add(ctx, addr, addr, 2);
7426
#if defined(TARGET_PPC64)
7427
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7428
    gen_qemu_st16(ctx, t0, addr);
7429
#else
7430
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7431
#endif
7432
    gen_addr_add(ctx, addr, addr, 2);
7433
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7434
    gen_qemu_st16(ctx, t0, addr);
7435
    tcg_temp_free(t0);
7436
    gen_addr_add(ctx, addr, addr, 2);
7437
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7438
}
7439

    
7440
static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7441
{
7442
    TCGv t0 = tcg_temp_new();
7443
#if defined(TARGET_PPC64)
7444
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7445
#else
7446
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7447
#endif
7448
    gen_qemu_st16(ctx, t0, addr);
7449
    gen_addr_add(ctx, addr, addr, 2);
7450
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7451
    gen_qemu_st16(ctx, t0, addr);
7452
    tcg_temp_free(t0);
7453
}
7454

    
7455
static always_inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7456
{
7457
#if defined(TARGET_PPC64)
7458
    TCGv t0 = tcg_temp_new();
7459
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7460
    gen_qemu_st16(ctx, t0, addr);
7461
    tcg_temp_free(t0);
7462
#else
7463
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7464
#endif
7465
    gen_addr_add(ctx, addr, addr, 2);
7466
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7467
}
7468

    
7469
static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7470
{
7471
#if defined(TARGET_PPC64)
7472
    TCGv t0 = tcg_temp_new();
7473
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7474
    gen_qemu_st32(ctx, t0, addr);
7475
    tcg_temp_free(t0);
7476
#else
7477
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7478
#endif
7479
}
7480

    
7481
static always_inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7482
{
7483
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7484
}
7485

    
7486
#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
7487
GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)                      \
7488
{                                                                             \
7489
    TCGv t0;                                                                  \
7490
    if (unlikely(!ctx->spe_enabled)) {                                        \
7491
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7492
        return;                                                               \
7493
    }                                                                         \
7494
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7495
    t0 = tcg_temp_new();                                                      \
7496
    if (Rc(ctx->opcode)) {                                                    \
7497
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7498
    } else {                                                                  \
7499
        gen_addr_reg_index(ctx, t0);                                          \
7500
    }                                                                         \
7501
    gen_op_##name(ctx, t0);                                                   \
7502
    tcg_temp_free(t0);                                                        \
7503
}
7504

    
7505
GEN_SPEOP_LDST(evldd, 0x00, 3);
7506
GEN_SPEOP_LDST(evldw, 0x01, 3);
7507
GEN_SPEOP_LDST(evldh, 0x02, 3);
7508
GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
7509
GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
7510
GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
7511
GEN_SPEOP_LDST(evlwhe, 0x08, 2);
7512
GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
7513
GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
7514
GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
7515
GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
7516

    
7517
GEN_SPEOP_LDST(evstdd, 0x10, 3);
7518
GEN_SPEOP_LDST(evstdw, 0x11, 3);
7519
GEN_SPEOP_LDST(evstdh, 0x12, 3);
7520
GEN_SPEOP_LDST(evstwhe, 0x18, 2);
7521
GEN_SPEOP_LDST(evstwho, 0x1A, 2);
7522
GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
7523
GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
7524

    
7525
/* Multiply and add - TODO */
7526
#if 0
7527
GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0x00000000, PPC_SPE);
7528
GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0x00000000, PPC_SPE);
7529
GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, PPC_SPE);
7530
GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0x00000000, PPC_SPE);
7531
GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, PPC_SPE);
7532
GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0x00000000, PPC_SPE);
7533
GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0x00000000, PPC_SPE);
7534
GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0x00000000, PPC_SPE);
7535
GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, PPC_SPE);
7536
GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0x00000000, PPC_SPE);
7537
GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, PPC_SPE);
7538
GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0x00000000, PPC_SPE);
7539

7540
GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
7541
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
7542
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
7543
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
7544
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
7545
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
7546
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
7547
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
7548
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
7549
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
7550
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
7551
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
7552
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
7553
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
7554

7555
GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
7556
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
7557
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
7558
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
7559
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
7560
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
7561

7562
GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
7563
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
7564
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
7565
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
7566
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
7567
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
7568
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
7569
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
7570
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
7571
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
7572
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
7573
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
7574

7575
GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
7576
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
7577
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
7578
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
7579
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
7580

7581
GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
7582
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
7583
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
7584
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
7585
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
7586
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
7587
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
7588
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
7589
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
7590
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
7591
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
7592
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
7593

7594
GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, PPC_SPE);
7595
GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, PPC_SPE);
7596
GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0x00000000, PPC_SPE);
7597
GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, PPC_SPE);
7598
GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0x00000000, PPC_SPE);
7599
#endif
7600

    
7601
/***                      SPE floating-point extension                     ***/
7602
#if defined(TARGET_PPC64)
7603
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
7604
static always_inline void gen_##name (DisasContext *ctx)                      \
7605
{                                                                             \
7606
    TCGv_i32 t0;                                                              \
7607
    TCGv t1;                                                                  \
7608
    t0 = tcg_temp_new_i32();                                                  \
7609
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
7610
    gen_helper_##name(t0, t0);                                                \
7611
    t1 = tcg_temp_new();                                                      \
7612
    tcg_gen_extu_i32_tl(t1, t0);                                              \
7613
    tcg_temp_free_i32(t0);                                                    \
7614
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7615
                    0xFFFFFFFF00000000ULL);                                   \
7616
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
7617
    tcg_temp_free(t1);                                                        \
7618
}
7619
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
7620
static always_inline void gen_##name (DisasContext *ctx)                      \
7621
{                                                                             \
7622
    TCGv_i32 t0;                                                              \
7623
    TCGv t1;                                                                  \
7624
    t0 = tcg_temp_new_i32();                                                  \
7625
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
7626
    t1 = tcg_temp_new();                                                      \
7627
    tcg_gen_extu_i32_tl(t1, t0);                                              \
7628
    tcg_temp_free_i32(t0);                                                    \
7629
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7630
                    0xFFFFFFFF00000000ULL);                                   \
7631
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
7632
    tcg_temp_free(t1);                                                        \
7633
}
7634
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
7635
static always_inline void gen_##name (DisasContext *ctx)                      \
7636
{                                                                             \
7637
    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
7638
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
7639
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
7640
    tcg_temp_free_i32(t0);                                                    \
7641
}
7642
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
7643
static always_inline void gen_##name (DisasContext *ctx)                      \
7644
{                                                                             \
7645
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7646
}
7647
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
7648
static always_inline void gen_##name (DisasContext *ctx)                      \
7649
{                                                                             \
7650
    TCGv_i32 t0, t1;                                                          \
7651
    TCGv_i64 t2;                                                              \
7652
    if (unlikely(!ctx->spe_enabled)) {                                        \
7653
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7654
        return;                                                               \
7655
    }                                                                         \
7656
    t0 = tcg_temp_new_i32();                                                  \
7657
    t1 = tcg_temp_new_i32();                                                  \
7658
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
7659
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
7660
    gen_helper_##name(t0, t0, t1);                                            \
7661
    tcg_temp_free_i32(t1);                                                    \
7662
    t2 = tcg_temp_new();                                                      \
7663
    tcg_gen_extu_i32_tl(t2, t0);                                              \
7664
    tcg_temp_free_i32(t0);                                                    \
7665
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7666
                    0xFFFFFFFF00000000ULL);                                   \
7667
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2);    \
7668
    tcg_temp_free(t2);                                                        \
7669
}
7670
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
7671
static always_inline void gen_##name (DisasContext *ctx)                      \
7672
{                                                                             \
7673
    if (unlikely(!ctx->spe_enabled)) {                                        \
7674
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7675
        return;                                                               \
7676
    }                                                                         \
7677
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],     \
7678
                      cpu_gpr[rB(ctx->opcode)]);                              \
7679
}
7680
#define GEN_SPEFPUOP_COMP_32(name)                                            \
7681
static always_inline void gen_##name (DisasContext *ctx)                      \
7682
{                                                                             \
7683
    TCGv_i32 t0, t1;                                                          \
7684
    if (unlikely(!ctx->spe_enabled)) {                                        \
7685
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7686
        return;                                                               \
7687
    }                                                                         \
7688
    t0 = tcg_temp_new_i32();                                                  \
7689
    t1 = tcg_temp_new_i32();                                                  \
7690
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
7691
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
7692
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
7693
    tcg_temp_free_i32(t0);                                                    \
7694
    tcg_temp_free_i32(t1);                                                    \
7695
}
7696
#define GEN_SPEFPUOP_COMP_64(name)                                            \
7697
static always_inline void gen_##name (DisasContext *ctx)                      \
7698
{                                                                             \
7699
    if (unlikely(!ctx->spe_enabled)) {                                        \
7700
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7701
        return;                                                               \
7702
    }                                                                         \
7703
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
7704
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7705
}
7706
#else
7707
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
7708
static always_inline void gen_##name (DisasContext *ctx)                      \
7709
{                                                                             \
7710
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7711
}
7712
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
7713
static always_inline void gen_##name (DisasContext *ctx)                      \
7714
{                                                                             \
7715
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7716
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
7717
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
7718
    tcg_temp_free_i64(t0);                                                    \
7719
}
7720
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
7721
static always_inline void gen_##name (DisasContext *ctx)                      \
7722
{                                                                             \
7723
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7724
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
7725
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7726
    tcg_temp_free_i64(t0);                                                    \
7727
}
7728
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
7729
static always_inline void gen_##name (DisasContext *ctx)                      \
7730
{                                                                             \
7731
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7732
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
7733
    gen_helper_##name(t0, t0);                                                \
7734
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7735
    tcg_temp_free_i64(t0);                                                    \
7736
}
7737
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
7738
static always_inline void gen_##name (DisasContext *ctx)                      \
7739
{                                                                             \
7740
    if (unlikely(!ctx->spe_enabled)) {                                        \
7741
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7742
        return;                                                               \
7743
    }                                                                         \
7744
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)],                               \
7745
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7746
}
7747
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
7748
static always_inline void gen_##name (DisasContext *ctx)                      \
7749
{                                                                             \
7750
    TCGv_i64 t0, t1;                                                          \
7751
    if (unlikely(!ctx->spe_enabled)) {                                        \
7752
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7753
        return;                                                               \
7754
    }                                                                         \
7755
    t0 = tcg_temp_new_i64();                                                  \
7756
    t1 = tcg_temp_new_i64();                                                  \
7757
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
7758
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
7759
    gen_helper_##name(t0, t0, t1);                                            \
7760
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7761
    tcg_temp_free_i64(t0);                                                    \
7762
    tcg_temp_free_i64(t1);                                                    \
7763
}
7764
#define GEN_SPEFPUOP_COMP_32(name)                                            \
7765
static always_inline void gen_##name (DisasContext *ctx)                      \
7766
{                                                                             \
7767
    if (unlikely(!ctx->spe_enabled)) {                                        \
7768
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7769
        return;                                                               \
7770
    }                                                                         \
7771
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
7772
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7773
}
7774
#define GEN_SPEFPUOP_COMP_64(name)                                            \
7775
static always_inline void gen_##name (DisasContext *ctx)                      \
7776
{                                                                             \
7777
    TCGv_i64 t0, t1;                                                          \
7778
    if (unlikely(!ctx->spe_enabled)) {                                        \
7779
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7780
        return;                                                               \
7781
    }                                                                         \
7782
    t0 = tcg_temp_new_i64();                                                  \
7783
    t1 = tcg_temp_new_i64();                                                  \
7784
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
7785
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
7786
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
7787
    tcg_temp_free_i64(t0);                                                    \
7788
    tcg_temp_free_i64(t1);                                                    \
7789
}
7790
#endif
7791

    
7792
/* Single precision floating-point vectors operations */
7793
/* Arithmetic */
7794
GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
7795
GEN_SPEFPUOP_ARITH2_64_64(evfssub);
7796
GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
7797
GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
7798
static always_inline void gen_evfsabs (DisasContext *ctx)
7799
{
7800
    if (unlikely(!ctx->spe_enabled)) {
7801
        gen_exception(ctx, POWERPC_EXCP_APU);
7802
        return;
7803
    }
7804
#if defined(TARGET_PPC64)
7805
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
7806
#else
7807
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
7808
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7809
#endif
7810
}
7811
static always_inline void gen_evfsnabs (DisasContext *ctx)
7812
{
7813
    if (unlikely(!ctx->spe_enabled)) {
7814
        gen_exception(ctx, POWERPC_EXCP_APU);
7815
        return;
7816
    }
7817
#if defined(TARGET_PPC64)
7818
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7819
#else
7820
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7821
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7822
#endif
7823
}
7824
static always_inline void gen_evfsneg (DisasContext *ctx)
7825
{
7826
    if (unlikely(!ctx->spe_enabled)) {
7827
        gen_exception(ctx, POWERPC_EXCP_APU);
7828
        return;
7829
    }
7830
#if defined(TARGET_PPC64)
7831
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7832
#else
7833
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7834
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7835
#endif
7836
}
7837

    
7838
/* Conversion */
7839
GEN_SPEFPUOP_CONV_64_64(evfscfui);
7840
GEN_SPEFPUOP_CONV_64_64(evfscfsi);
7841
GEN_SPEFPUOP_CONV_64_64(evfscfuf);
7842
GEN_SPEFPUOP_CONV_64_64(evfscfsf);
7843
GEN_SPEFPUOP_CONV_64_64(evfsctui);
7844
GEN_SPEFPUOP_CONV_64_64(evfsctsi);
7845
GEN_SPEFPUOP_CONV_64_64(evfsctuf);
7846
GEN_SPEFPUOP_CONV_64_64(evfsctsf);
7847
GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
7848
GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
7849

    
7850
/* Comparison */
7851
GEN_SPEFPUOP_COMP_64(evfscmpgt);
7852
GEN_SPEFPUOP_COMP_64(evfscmplt);
7853
GEN_SPEFPUOP_COMP_64(evfscmpeq);
7854
GEN_SPEFPUOP_COMP_64(evfststgt);
7855
GEN_SPEFPUOP_COMP_64(evfststlt);
7856
GEN_SPEFPUOP_COMP_64(evfststeq);
7857

    
7858
/* Opcodes definitions */
7859
GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
7860
GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
7861
GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
7862
GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
7863
GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7864
GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7865
GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7866
GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7867
GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7868
GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7869
GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7870
GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
7871
GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7872
GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
7873

    
7874
/* Single precision floating-point operations */
7875
/* Arithmetic */
7876
GEN_SPEFPUOP_ARITH2_32_32(efsadd);
7877
GEN_SPEFPUOP_ARITH2_32_32(efssub);
7878
GEN_SPEFPUOP_ARITH2_32_32(efsmul);
7879
GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
7880
static always_inline void gen_efsabs (DisasContext *ctx)
7881
{
7882
    if (unlikely(!ctx->spe_enabled)) {
7883
        gen_exception(ctx, POWERPC_EXCP_APU);
7884
        return;
7885
    }
7886
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
7887
}
7888
static always_inline void gen_efsnabs (DisasContext *ctx)
7889
{
7890
    if (unlikely(!ctx->spe_enabled)) {
7891
        gen_exception(ctx, POWERPC_EXCP_APU);
7892
        return;
7893
    }
7894
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7895
}
7896
static always_inline void gen_efsneg (DisasContext *ctx)
7897
{
7898
    if (unlikely(!ctx->spe_enabled)) {
7899
        gen_exception(ctx, POWERPC_EXCP_APU);
7900
        return;
7901
    }
7902
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7903
}
7904

    
7905
/* Conversion */
7906
GEN_SPEFPUOP_CONV_32_32(efscfui);
7907
GEN_SPEFPUOP_CONV_32_32(efscfsi);
7908
GEN_SPEFPUOP_CONV_32_32(efscfuf);
7909
GEN_SPEFPUOP_CONV_32_32(efscfsf);
7910
GEN_SPEFPUOP_CONV_32_32(efsctui);
7911
GEN_SPEFPUOP_CONV_32_32(efsctsi);
7912
GEN_SPEFPUOP_CONV_32_32(efsctuf);
7913
GEN_SPEFPUOP_CONV_32_32(efsctsf);
7914
GEN_SPEFPUOP_CONV_32_32(efsctuiz);
7915
GEN_SPEFPUOP_CONV_32_32(efsctsiz);
7916
GEN_SPEFPUOP_CONV_32_64(efscfd);
7917

    
7918
/* Comparison */
7919
GEN_SPEFPUOP_COMP_32(efscmpgt);
7920
GEN_SPEFPUOP_COMP_32(efscmplt);
7921
GEN_SPEFPUOP_COMP_32(efscmpeq);
7922
GEN_SPEFPUOP_COMP_32(efststgt);
7923
GEN_SPEFPUOP_COMP_32(efststlt);
7924
GEN_SPEFPUOP_COMP_32(efststeq);
7925

    
7926
/* Opcodes definitions */
7927
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
7928
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
7929
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
7930
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
7931
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7932
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7933
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7934
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7935
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7936
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7937
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7938
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
7939
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7940
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
7941

    
7942
/* Double precision floating-point operations */
7943
/* Arithmetic */
7944
GEN_SPEFPUOP_ARITH2_64_64(efdadd);
7945
GEN_SPEFPUOP_ARITH2_64_64(efdsub);
7946
GEN_SPEFPUOP_ARITH2_64_64(efdmul);
7947
GEN_SPEFPUOP_ARITH2_64_64(efddiv);
7948
static always_inline void gen_efdabs (DisasContext *ctx)
7949
{
7950
    if (unlikely(!ctx->spe_enabled)) {
7951
        gen_exception(ctx, POWERPC_EXCP_APU);
7952
        return;
7953
    }
7954
#if defined(TARGET_PPC64)
7955
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
7956
#else
7957
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7958
#endif
7959
}
7960
static always_inline void gen_efdnabs (DisasContext *ctx)
7961
{
7962
    if (unlikely(!ctx->spe_enabled)) {
7963
        gen_exception(ctx, POWERPC_EXCP_APU);
7964
        return;
7965
    }
7966
#if defined(TARGET_PPC64)
7967
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7968
#else
7969
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7970
#endif
7971
}
7972
static always_inline void gen_efdneg (DisasContext *ctx)
7973
{
7974
    if (unlikely(!ctx->spe_enabled)) {
7975
        gen_exception(ctx, POWERPC_EXCP_APU);
7976
        return;
7977
    }
7978
#if defined(TARGET_PPC64)
7979
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7980
#else
7981
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7982
#endif
7983
}
7984

    
7985
/* Conversion */
7986
GEN_SPEFPUOP_CONV_64_32(efdcfui);
7987
GEN_SPEFPUOP_CONV_64_32(efdcfsi);
7988
GEN_SPEFPUOP_CONV_64_32(efdcfuf);
7989
GEN_SPEFPUOP_CONV_64_32(efdcfsf);
7990
GEN_SPEFPUOP_CONV_32_64(efdctui);
7991
GEN_SPEFPUOP_CONV_32_64(efdctsi);
7992
GEN_SPEFPUOP_CONV_32_64(efdctuf);
7993
GEN_SPEFPUOP_CONV_32_64(efdctsf);
7994
GEN_SPEFPUOP_CONV_32_64(efdctuiz);
7995
GEN_SPEFPUOP_CONV_32_64(efdctsiz);
7996
GEN_SPEFPUOP_CONV_64_32(efdcfs);
7997
GEN_SPEFPUOP_CONV_64_64(efdcfuid);
7998
GEN_SPEFPUOP_CONV_64_64(efdcfsid);
7999
GEN_SPEFPUOP_CONV_64_64(efdctuidz);
8000
GEN_SPEFPUOP_CONV_64_64(efdctsidz);
8001

    
8002
/* Comparison */
8003
GEN_SPEFPUOP_COMP_64(efdcmpgt);
8004
GEN_SPEFPUOP_COMP_64(efdcmplt);
8005
GEN_SPEFPUOP_COMP_64(efdcmpeq);
8006
GEN_SPEFPUOP_COMP_64(efdtstgt);
8007
GEN_SPEFPUOP_COMP_64(efdtstlt);
8008
GEN_SPEFPUOP_COMP_64(efdtsteq);
8009

    
8010
/* Opcodes definitions */
8011
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
8012
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8013
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
8014
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
8015
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
8016
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8017
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
8018
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
8019
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8020
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8021
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8022
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8023
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8024
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8025
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
8026
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
8027

    
8028
/* End opcode list */
8029
GEN_OPCODE_MARK(end);
8030

    
8031
#include "translate_init.c"
8032
#include "helper_regs.h"
8033

    
8034
/*****************************************************************************/
8035
/* Misc PowerPC helpers */
8036
void cpu_dump_state (CPUState *env, FILE *f,
8037
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8038
                     int flags)
8039
{
8040
#define RGPL  4
8041
#define RFPL  4
8042

    
8043
    int i;
8044

    
8045
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
8046
                env->nip, env->lr, env->ctr, env->xer);
8047
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
8048
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
8049
#if !defined(NO_TIMER_DUMP)
8050
    cpu_fprintf(f, "TB %08x %08x "
8051
#if !defined(CONFIG_USER_ONLY)
8052
                "DECR %08x"
8053
#endif
8054
                "\n",
8055
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
8056
#if !defined(CONFIG_USER_ONLY)
8057
                , cpu_ppc_load_decr(env)
8058
#endif
8059
                );
8060
#endif
8061
    for (i = 0; i < 32; i++) {
8062
        if ((i & (RGPL - 1)) == 0)
8063
            cpu_fprintf(f, "GPR%02d", i);
8064
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
8065
        if ((i & (RGPL - 1)) == (RGPL - 1))
8066
            cpu_fprintf(f, "\n");
8067
    }
8068
    cpu_fprintf(f, "CR ");
8069
    for (i = 0; i < 8; i++)
8070
        cpu_fprintf(f, "%01x", env->crf[i]);
8071
    cpu_fprintf(f, "  [");
8072
    for (i = 0; i < 8; i++) {
8073
        char a = '-';
8074
        if (env->crf[i] & 0x08)
8075
            a = 'L';
8076
        else if (env->crf[i] & 0x04)
8077
            a = 'G';
8078
        else if (env->crf[i] & 0x02)
8079
            a = 'E';
8080
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
8081
    }
8082
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
8083
    for (i = 0; i < 32; i++) {
8084
        if ((i & (RFPL - 1)) == 0)
8085
            cpu_fprintf(f, "FPR%02d", i);
8086
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
8087
        if ((i & (RFPL - 1)) == (RFPL - 1))
8088
            cpu_fprintf(f, "\n");
8089
    }
8090
    cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
8091
#if !defined(CONFIG_USER_ONLY)
8092
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
8093
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
8094
#endif
8095

    
8096
#undef RGPL
8097
#undef RFPL
8098
}
8099

    
8100
void cpu_dump_statistics (CPUState *env, FILE*f,
8101
                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8102
                          int flags)
8103
{
8104
#if defined(DO_PPC_STATISTICS)
8105
    opc_handler_t **t1, **t2, **t3, *handler;
8106
    int op1, op2, op3;
8107

    
8108
    t1 = env->opcodes;
8109
    for (op1 = 0; op1 < 64; op1++) {
8110
        handler = t1[op1];
8111
        if (is_indirect_opcode(handler)) {
8112
            t2 = ind_table(handler);
8113
            for (op2 = 0; op2 < 32; op2++) {
8114
                handler = t2[op2];
8115
                if (is_indirect_opcode(handler)) {
8116
                    t3 = ind_table(handler);
8117
                    for (op3 = 0; op3 < 32; op3++) {
8118
                        handler = t3[op3];
8119
                        if (handler->count == 0)
8120
                            continue;
8121
                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
8122
                                    "%016llx %lld\n",
8123
                                    op1, op2, op3, op1, (op3 << 5) | op2,
8124
                                    handler->oname,
8125
                                    handler->count, handler->count);
8126
                    }
8127
                } else {
8128
                    if (handler->count == 0)
8129
                        continue;
8130
                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
8131
                                "%016llx %lld\n",
8132
                                op1, op2, op1, op2, handler->oname,
8133
                                handler->count, handler->count);
8134
                }
8135
            }
8136
        } else {
8137
            if (handler->count == 0)
8138
                continue;
8139
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016llx %lld\n",
8140
                        op1, op1, handler->oname,
8141
                        handler->count, handler->count);
8142
        }
8143
    }
8144
#endif
8145
}
8146

    
8147
/*****************************************************************************/
8148
static always_inline void gen_intermediate_code_internal (CPUState *env,
8149
                                                          TranslationBlock *tb,
8150
                                                          int search_pc)
8151
{
8152
    DisasContext ctx, *ctxp = &ctx;
8153
    opc_handler_t **table, *handler;
8154
    target_ulong pc_start;
8155
    uint16_t *gen_opc_end;
8156
    CPUBreakpoint *bp;
8157
    int j, lj = -1;
8158
    int num_insns;
8159
    int max_insns;
8160

    
8161
    pc_start = tb->pc;
8162
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8163
    ctx.nip = pc_start;
8164
    ctx.tb = tb;
8165
    ctx.exception = POWERPC_EXCP_NONE;
8166
    ctx.spr_cb = env->spr_cb;
8167
    ctx.mem_idx = env->mmu_idx;
8168
    ctx.access_type = -1;
8169
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
8170
#if defined(TARGET_PPC64)
8171
    ctx.sf_mode = msr_sf;
8172
#endif
8173
    ctx.fpu_enabled = msr_fp;
8174
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
8175
        ctx.spe_enabled = msr_spe;
8176
    else
8177
        ctx.spe_enabled = 0;
8178
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
8179
        ctx.altivec_enabled = msr_vr;
8180
    else
8181
        ctx.altivec_enabled = 0;
8182
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8183
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
8184
    else
8185
        ctx.singlestep_enabled = 0;
8186
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8187
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
8188
    if (unlikely(env->singlestep_enabled))
8189
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
8190
#if defined (DO_SINGLE_STEP) && 0
8191
    /* Single step trace mode */
8192
    msr_se = 1;
8193
#endif
8194
    num_insns = 0;
8195
    max_insns = tb->cflags & CF_COUNT_MASK;
8196
    if (max_insns == 0)
8197
        max_insns = CF_COUNT_MASK;
8198

    
8199
    gen_icount_start();
8200
    /* Set env in case of segfault during code fetch */
8201
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
8202
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8203
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8204
                if (bp->pc == ctx.nip) {
8205
                    gen_debug_exception(ctxp);
8206
                    break;
8207
                }
8208
            }
8209
        }
8210
        if (unlikely(search_pc)) {
8211
            j = gen_opc_ptr - gen_opc_buf;
8212
            if (lj < j) {
8213
                lj++;
8214
                while (lj < j)
8215
                    gen_opc_instr_start[lj++] = 0;
8216
                gen_opc_pc[lj] = ctx.nip;
8217
                gen_opc_instr_start[lj] = 1;
8218
                gen_opc_icount[lj] = num_insns;
8219
            }
8220
        }
8221
        LOG_DISAS("----------------\n");
8222
        LOG_DISAS("nip=" ADDRX " super=%d ir=%d\n",
8223
                  ctx.nip, ctx.mem_idx, (int)msr_ir);
8224
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8225
            gen_io_start();
8226
        if (unlikely(ctx.le_mode)) {
8227
            ctx.opcode = bswap32(ldl_code(ctx.nip));
8228
        } else {
8229
            ctx.opcode = ldl_code(ctx.nip);
8230
        }
8231
        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
8232
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
8233
                    opc3(ctx.opcode), little_endian ? "little" : "big");
8234
        ctx.nip += 4;
8235
        table = env->opcodes;
8236
        num_insns++;
8237
        handler = table[opc1(ctx.opcode)];
8238
        if (is_indirect_opcode(handler)) {
8239
            table = ind_table(handler);
8240
            handler = table[opc2(ctx.opcode)];
8241
            if (is_indirect_opcode(handler)) {
8242
                table = ind_table(handler);
8243
                handler = table[opc3(ctx.opcode)];
8244
            }
8245
        }
8246
        /* Is opcode *REALLY* valid ? */
8247
        if (unlikely(handler->handler == &gen_invalid)) {
8248
            if (qemu_log_enabled()) {
8249
                qemu_log("invalid/unsupported opcode: "
8250
                          "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
8251
                          opc1(ctx.opcode), opc2(ctx.opcode),
8252
                          opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
8253
            } else {
8254
                printf("invalid/unsupported opcode: "
8255
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
8256
                       opc1(ctx.opcode), opc2(ctx.opcode),
8257
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
8258
            }
8259
        } else {
8260
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
8261
                if (qemu_log_enabled()) {
8262
                    qemu_log("invalid bits: %08x for opcode: "
8263
                              "%02x - %02x - %02x (%08x) " ADDRX "\n",
8264
                              ctx.opcode & handler->inval, opc1(ctx.opcode),
8265
                              opc2(ctx.opcode), opc3(ctx.opcode),
8266
                              ctx.opcode, ctx.nip - 4);
8267
                } else {
8268
                    printf("invalid bits: %08x for opcode: "
8269
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
8270
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
8271
                           opc2(ctx.opcode), opc3(ctx.opcode),
8272
                           ctx.opcode, ctx.nip - 4);
8273
                }
8274
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
8275
                break;
8276
            }
8277
        }
8278
        (*(handler->handler))(&ctx);
8279
#if defined(DO_PPC_STATISTICS)
8280
        handler->count++;
8281
#endif
8282
        /* Check trace mode exceptions */
8283
        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
8284
                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
8285
                     ctx.exception != POWERPC_SYSCALL &&
8286
                     ctx.exception != POWERPC_EXCP_TRAP &&
8287
                     ctx.exception != POWERPC_EXCP_BRANCH)) {
8288
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
8289
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
8290
                            (env->singlestep_enabled) ||
8291
                            num_insns >= max_insns)) {
8292
            /* if we reach a page boundary or are single stepping, stop
8293
             * generation
8294
             */
8295
            break;
8296
        }
8297
#if defined (DO_SINGLE_STEP)
8298
        break;
8299
#endif
8300
    }
8301
    if (tb->cflags & CF_LAST_IO)
8302
        gen_io_end();
8303
    if (ctx.exception == POWERPC_EXCP_NONE) {
8304
        gen_goto_tb(&ctx, 0, ctx.nip);
8305
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
8306
        if (unlikely(env->singlestep_enabled)) {
8307
            gen_debug_exception(ctxp);
8308
        }
8309
        /* Generate the return instruction */
8310
        tcg_gen_exit_tb(0);
8311
    }
8312
    gen_icount_end(tb, num_insns);
8313
    *gen_opc_ptr = INDEX_op_end;
8314
    if (unlikely(search_pc)) {
8315
        j = gen_opc_ptr - gen_opc_buf;
8316
        lj++;
8317
        while (lj <= j)
8318
            gen_opc_instr_start[lj++] = 0;
8319
    } else {
8320
        tb->size = ctx.nip - pc_start;
8321
        tb->icount = num_insns;
8322
    }
8323
#if defined(DEBUG_DISAS)
8324
    qemu_log_mask(CPU_LOG_TB_CPU, "---------------- excp: %04x\n", ctx.exception);
8325
    log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
8326
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8327
        int flags;
8328
        flags = env->bfd_mach;
8329
        flags |= ctx.le_mode << 16;
8330
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
8331
        log_target_disas(pc_start, ctx.nip - pc_start, flags);
8332
        qemu_log("\n");
8333
    }
8334
#endif
8335
}
8336

    
8337
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8338
{
8339
    gen_intermediate_code_internal(env, tb, 0);
8340
}
8341

    
8342
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8343
{
8344
    gen_intermediate_code_internal(env, tb, 1);
8345
}
8346

    
8347
void gen_pc_load(CPUState *env, TranslationBlock *tb,
8348
                unsigned long searched_pc, int pc_pos, void *puc)
8349
{
8350
    env->nip = gen_opc_pc[pc_pos];
8351
}