Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ 2c0d18dd

History | View | Annotate | Download (346.8 kB)

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

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

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

    
78
#include "gen-icount.h"
79

    
80
void ppc_translate_init(void)
81
{
82
    int i;
83
    char* p;
84
    size_t cpu_reg_names_size;
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
    cpu_reg_names_size = sizeof(cpu_reg_names);
94

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
175
    done_init = 1;
176
}
177

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

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

    
216
static inline void gen_reset_fpstatus(void)
217
{
218
    gen_helper_reset_fpstatus();
219
}
220

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

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

    
240
    tcg_temp_free_i32(t0);
241
}
242

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

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

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

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

    
287
static inline void gen_debug_exception(DisasContext *ctx)
288
{
289
    TCGv_i32 t0;
290

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

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

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

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

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

    
319
#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2)             \
320
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
321

    
322
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
323
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
324

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

    
328
typedef struct opcode_t {
329
    unsigned char opc1, opc2, opc3;
330
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
331
    unsigned char pad[5];
332
#else
333
    unsigned char pad[1];
334
#endif
335
    opc_handler_t handler;
336
    const char *oname;
337
} opcode_t;
338

    
339
/*****************************************************************************/
340
/***                           Instruction decoding                        ***/
341
#define EXTRACT_HELPER(name, shift, nb)                                       \
342
static inline uint32_t name(uint32_t opcode)                                  \
343
{                                                                             \
344
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
345
}
346

    
347
#define EXTRACT_SHELPER(name, shift, nb)                                      \
348
static inline int32_t name(uint32_t opcode)                                   \
349
{                                                                             \
350
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
351
}
352

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

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

    
408
EXTRACT_HELPER(CRM, 12, 8);
409
EXTRACT_HELPER(FM, 17, 8);
410
EXTRACT_HELPER(SR, 16, 4);
411
EXTRACT_HELPER(FPIMM, 12, 4);
412

    
413
/***                            Jump target decoding                       ***/
414
/* Displacement */
415
EXTRACT_SHELPER(d, 0, 16);
416
/* Immediate address */
417
static inline target_ulong LI(uint32_t opcode)
418
{
419
    return (opcode >> 0) & 0x03FFFFFC;
420
}
421

    
422
static inline uint32_t BD(uint32_t opcode)
423
{
424
    return (opcode >> 0) & 0xFFFC;
425
}
426

    
427
EXTRACT_HELPER(BO, 21, 5);
428
EXTRACT_HELPER(BI, 16, 5);
429
/* Absolute/relative address */
430
EXTRACT_HELPER(AA, 1, 1);
431
/* Link */
432
EXTRACT_HELPER(LK, 0, 1);
433

    
434
/* Create a mask between <start> and <end> bits */
435
static inline target_ulong MASK(uint32_t start, uint32_t end)
436
{
437
    target_ulong ret;
438

    
439
#if defined(TARGET_PPC64)
440
    if (likely(start == 0)) {
441
        ret = UINT64_MAX << (63 - end);
442
    } else if (likely(end == 63)) {
443
        ret = UINT64_MAX >> start;
444
    }
445
#else
446
    if (likely(start == 0)) {
447
        ret = UINT32_MAX << (31  - end);
448
    } else if (likely(end == 31)) {
449
        ret = UINT32_MAX >> start;
450
    }
451
#endif
452
    else {
453
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
454
            (((target_ulong)(-1ULL) >> (end)) >> 1);
455
        if (unlikely(start > end))
456
            return ~ret;
457
    }
458

    
459
    return ret;
460
}
461

    
462
/*****************************************************************************/
463
/* PowerPC instructions table                                                */
464

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

    
527
/* SPR load/store helpers */
528
static inline void gen_load_spr(TCGv t, int reg)
529
{
530
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
531
}
532

    
533
static inline void gen_store_spr(int reg, TCGv t)
534
{
535
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
536
}
537

    
538
/* Invalid instruction */
539
static void gen_invalid(DisasContext *ctx)
540
{
541
    gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
542
}
543

    
544
static opc_handler_t invalid_handler = {
545
    .inval   = 0xFFFFFFFF,
546
    .type    = PPC_NONE,
547
    .type2   = PPC_NONE,
548
    .handler = gen_invalid,
549
};
550

    
551
/***                           Integer comparison                          ***/
552

    
553
static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
554
{
555
    int l1, l2, l3;
556

    
557
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
558
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
559
    tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);
560

    
561
    l1 = gen_new_label();
562
    l2 = gen_new_label();
563
    l3 = gen_new_label();
564
    if (s) {
565
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
566
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
567
    } else {
568
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
569
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
570
    }
571
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
572
    tcg_gen_br(l3);
573
    gen_set_label(l1);
574
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
575
    tcg_gen_br(l3);
576
    gen_set_label(l2);
577
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
578
    gen_set_label(l3);
579
}
580

    
581
static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
582
{
583
    TCGv t0 = tcg_const_local_tl(arg1);
584
    gen_op_cmp(arg0, t0, s, crf);
585
    tcg_temp_free(t0);
586
}
587

    
588
#if defined(TARGET_PPC64)
589
static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
590
{
591
    TCGv t0, t1;
592
    t0 = tcg_temp_local_new();
593
    t1 = tcg_temp_local_new();
594
    if (s) {
595
        tcg_gen_ext32s_tl(t0, arg0);
596
        tcg_gen_ext32s_tl(t1, arg1);
597
    } else {
598
        tcg_gen_ext32u_tl(t0, arg0);
599
        tcg_gen_ext32u_tl(t1, arg1);
600
    }
601
    gen_op_cmp(t0, t1, s, crf);
602
    tcg_temp_free(t1);
603
    tcg_temp_free(t0);
604
}
605

    
606
static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
607
{
608
    TCGv t0 = tcg_const_local_tl(arg1);
609
    gen_op_cmp32(arg0, t0, s, crf);
610
    tcg_temp_free(t0);
611
}
612
#endif
613

    
614
static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
615
{
616
#if defined(TARGET_PPC64)
617
    if (!(ctx->sf_mode))
618
        gen_op_cmpi32(reg, 0, 1, 0);
619
    else
620
#endif
621
        gen_op_cmpi(reg, 0, 1, 0);
622
}
623

    
624
/* cmp */
625
static void gen_cmp(DisasContext *ctx)
626
{
627
#if defined(TARGET_PPC64)
628
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
629
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
630
                     1, crfD(ctx->opcode));
631
    else
632
#endif
633
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
634
                   1, crfD(ctx->opcode));
635
}
636

    
637
/* cmpi */
638
static void gen_cmpi(DisasContext *ctx)
639
{
640
#if defined(TARGET_PPC64)
641
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
642
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
643
                      1, crfD(ctx->opcode));
644
    else
645
#endif
646
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
647
                    1, crfD(ctx->opcode));
648
}
649

    
650
/* cmpl */
651
static void gen_cmpl(DisasContext *ctx)
652
{
653
#if defined(TARGET_PPC64)
654
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
655
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
656
                     0, crfD(ctx->opcode));
657
    else
658
#endif
659
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
660
                   0, crfD(ctx->opcode));
661
}
662

    
663
/* cmpli */
664
static void gen_cmpli(DisasContext *ctx)
665
{
666
#if defined(TARGET_PPC64)
667
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
668
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
669
                      0, crfD(ctx->opcode));
670
    else
671
#endif
672
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
673
                    0, crfD(ctx->opcode));
674
}
675

    
676
/* isel (PowerPC 2.03 specification) */
677
static void gen_isel(DisasContext *ctx)
678
{
679
    int l1, l2;
680
    uint32_t bi = rC(ctx->opcode);
681
    uint32_t mask;
682
    TCGv_i32 t0;
683

    
684
    l1 = gen_new_label();
685
    l2 = gen_new_label();
686

    
687
    mask = 1 << (3 - (bi & 0x03));
688
    t0 = tcg_temp_new_i32();
689
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
690
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
691
    if (rA(ctx->opcode) == 0)
692
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
693
    else
694
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
695
    tcg_gen_br(l2);
696
    gen_set_label(l1);
697
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
698
    gen_set_label(l2);
699
    tcg_temp_free_i32(t0);
700
}
701

    
702
/***                           Integer arithmetic                          ***/
703

    
704
static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
705
                                           TCGv arg1, TCGv arg2, int sub)
706
{
707
    int l1;
708
    TCGv t0;
709

    
710
    l1 = gen_new_label();
711
    /* Start with XER OV disabled, the most likely case */
712
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
713
    t0 = tcg_temp_local_new();
714
    tcg_gen_xor_tl(t0, arg0, arg1);
715
#if defined(TARGET_PPC64)
716
    if (!ctx->sf_mode)
717
        tcg_gen_ext32s_tl(t0, t0);
718
#endif
719
    if (sub)
720
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
721
    else
722
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
723
    tcg_gen_xor_tl(t0, arg1, arg2);
724
#if defined(TARGET_PPC64)
725
    if (!ctx->sf_mode)
726
        tcg_gen_ext32s_tl(t0, t0);
727
#endif
728
    if (sub)
729
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
730
    else
731
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
732
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
733
    gen_set_label(l1);
734
    tcg_temp_free(t0);
735
}
736

    
737
static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1,
738
                                           TCGv arg2, int sub)
739
{
740
    int l1 = gen_new_label();
741

    
742
#if defined(TARGET_PPC64)
743
    if (!(ctx->sf_mode)) {
744
        TCGv t0, t1;
745
        t0 = tcg_temp_new();
746
        t1 = tcg_temp_new();
747

    
748
        tcg_gen_ext32u_tl(t0, arg1);
749
        tcg_gen_ext32u_tl(t1, arg2);
750
        if (sub) {
751
            tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
752
        } else {
753
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
754
        }
755
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
756
        gen_set_label(l1);
757
        tcg_temp_free(t0);
758
        tcg_temp_free(t1);
759
    } else
760
#endif
761
    {
762
        if (sub) {
763
            tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
764
        } else {
765
            tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
766
        }
767
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
768
        gen_set_label(l1);
769
    }
770
}
771

    
772
/* Common add function */
773
static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
774
                                    TCGv arg2, int add_ca, int compute_ca,
775
                                    int compute_ov)
776
{
777
    TCGv t0, t1;
778

    
779
    if ((!compute_ca && !compute_ov) ||
780
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
781
        t0 = ret;
782
    } else {
783
        t0 = tcg_temp_local_new();
784
    }
785

    
786
    if (add_ca) {
787
        t1 = tcg_temp_local_new();
788
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
789
        tcg_gen_shri_tl(t1, t1, XER_CA);
790
    } else {
791
        TCGV_UNUSED(t1);
792
    }
793

    
794
    if (compute_ca && compute_ov) {
795
        /* Start with XER CA and OV disabled, the most likely case */
796
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
797
    } else if (compute_ca) {
798
        /* Start with XER CA disabled, the most likely case */
799
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
800
    } else if (compute_ov) {
801
        /* Start with XER OV disabled, the most likely case */
802
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
803
    }
804

    
805
    tcg_gen_add_tl(t0, arg1, arg2);
806

    
807
    if (compute_ca) {
808
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
809
    }
810
    if (add_ca) {
811
        tcg_gen_add_tl(t0, t0, t1);
812
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
813
        tcg_temp_free(t1);
814
    }
815
    if (compute_ov) {
816
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
817
    }
818

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

    
822
    if (!TCGV_EQUAL(t0, ret)) {
823
        tcg_gen_mov_tl(ret, t0);
824
        tcg_temp_free(t0);
825
    }
826
}
827
/* Add functions with two operands */
828
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
829
static void glue(gen_, name)(DisasContext *ctx)                                       \
830
{                                                                             \
831
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
832
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
833
                     add_ca, compute_ca, compute_ov);                         \
834
}
835
/* Add functions with one operand and one immediate */
836
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
837
                                add_ca, compute_ca, compute_ov)               \
838
static void glue(gen_, name)(DisasContext *ctx)                                       \
839
{                                                                             \
840
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
841
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
842
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
843
                     add_ca, compute_ca, compute_ov);                         \
844
    tcg_temp_free(t0);                                                        \
845
}
846

    
847
/* add  add.  addo  addo. */
848
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
849
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
850
/* addc  addc.  addco  addco. */
851
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
852
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
853
/* adde  adde.  addeo  addeo. */
854
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
855
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
856
/* addme  addme.  addmeo  addmeo.  */
857
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
858
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
859
/* addze  addze.  addzeo  addzeo.*/
860
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
861
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
862
/* addi */
863
static void gen_addi(DisasContext *ctx)
864
{
865
    target_long simm = SIMM(ctx->opcode);
866

    
867
    if (rA(ctx->opcode) == 0) {
868
        /* li case */
869
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
870
    } else {
871
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
872
    }
873
}
874
/* addic  addic.*/
875
static inline void gen_op_addic(DisasContext *ctx, TCGv ret, TCGv arg1,
876
                                int compute_Rc0)
877
{
878
    target_long simm = SIMM(ctx->opcode);
879

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

    
883
    if (likely(simm != 0)) {
884
        TCGv t0 = tcg_temp_local_new();
885
        tcg_gen_addi_tl(t0, arg1, simm);
886
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
887
        tcg_gen_mov_tl(ret, t0);
888
        tcg_temp_free(t0);
889
    } else {
890
        tcg_gen_mov_tl(ret, arg1);
891
    }
892
    if (compute_Rc0) {
893
        gen_set_Rc0(ctx, ret);
894
    }
895
}
896

    
897
static void gen_addic(DisasContext *ctx)
898
{
899
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
900
}
901

    
902
static void gen_addic_(DisasContext *ctx)
903
{
904
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
905
}
906

    
907
/* addis */
908
static void gen_addis(DisasContext *ctx)
909
{
910
    target_long simm = SIMM(ctx->opcode);
911

    
912
    if (rA(ctx->opcode) == 0) {
913
        /* lis case */
914
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
915
    } else {
916
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
917
    }
918
}
919

    
920
static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
921
                                     TCGv arg2, int sign, int compute_ov)
922
{
923
    int l1 = gen_new_label();
924
    int l2 = gen_new_label();
925
    TCGv_i32 t0 = tcg_temp_local_new_i32();
926
    TCGv_i32 t1 = tcg_temp_local_new_i32();
927

    
928
    tcg_gen_trunc_tl_i32(t0, arg1);
929
    tcg_gen_trunc_tl_i32(t1, arg2);
930
    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
931
    if (sign) {
932
        int l3 = gen_new_label();
933
        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
934
        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
935
        gen_set_label(l3);
936
        tcg_gen_div_i32(t0, t0, t1);
937
    } else {
938
        tcg_gen_divu_i32(t0, t0, t1);
939
    }
940
    if (compute_ov) {
941
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
942
    }
943
    tcg_gen_br(l2);
944
    gen_set_label(l1);
945
    if (sign) {
946
        tcg_gen_sari_i32(t0, t0, 31);
947
    } else {
948
        tcg_gen_movi_i32(t0, 0);
949
    }
950
    if (compute_ov) {
951
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
952
    }
953
    gen_set_label(l2);
954
    tcg_gen_extu_i32_tl(ret, t0);
955
    tcg_temp_free_i32(t0);
956
    tcg_temp_free_i32(t1);
957
    if (unlikely(Rc(ctx->opcode) != 0))
958
        gen_set_Rc0(ctx, ret);
959
}
960
/* Div functions */
961
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
962
static void glue(gen_, name)(DisasContext *ctx)                                       \
963
{                                                                             \
964
    gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)],                          \
965
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
966
                     sign, compute_ov);                                       \
967
}
968
/* divwu  divwu.  divwuo  divwuo.   */
969
GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
970
GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
971
/* divw  divw.  divwo  divwo.   */
972
GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
973
GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
974
#if defined(TARGET_PPC64)
975
static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
976
                                     TCGv arg2, int sign, int compute_ov)
977
{
978
    int l1 = gen_new_label();
979
    int l2 = gen_new_label();
980

    
981
    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
982
    if (sign) {
983
        int l3 = gen_new_label();
984
        tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
985
        tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
986
        gen_set_label(l3);
987
        tcg_gen_div_i64(ret, arg1, arg2);
988
    } else {
989
        tcg_gen_divu_i64(ret, arg1, arg2);
990
    }
991
    if (compute_ov) {
992
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
993
    }
994
    tcg_gen_br(l2);
995
    gen_set_label(l1);
996
    if (sign) {
997
        tcg_gen_sari_i64(ret, arg1, 63);
998
    } else {
999
        tcg_gen_movi_i64(ret, 0);
1000
    }
1001
    if (compute_ov) {
1002
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1003
    }
1004
    gen_set_label(l2);
1005
    if (unlikely(Rc(ctx->opcode) != 0))
1006
        gen_set_Rc0(ctx, ret);
1007
}
1008
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
1009
static void glue(gen_, name)(DisasContext *ctx)                                       \
1010
{                                                                             \
1011
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1012
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1013
                      sign, compute_ov);                                      \
1014
}
1015
/* divwu  divwu.  divwuo  divwuo.   */
1016
GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1017
GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1018
/* divw  divw.  divwo  divwo.   */
1019
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1020
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1021
#endif
1022

    
1023
/* mulhw  mulhw. */
1024
static void gen_mulhw(DisasContext *ctx)
1025
{
1026
    TCGv_i64 t0, t1;
1027

    
1028
    t0 = tcg_temp_new_i64();
1029
    t1 = tcg_temp_new_i64();
1030
#if defined(TARGET_PPC64)
1031
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1032
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1033
    tcg_gen_mul_i64(t0, t0, t1);
1034
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1035
#else
1036
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1037
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1038
    tcg_gen_mul_i64(t0, t0, t1);
1039
    tcg_gen_shri_i64(t0, t0, 32);
1040
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1041
#endif
1042
    tcg_temp_free_i64(t0);
1043
    tcg_temp_free_i64(t1);
1044
    if (unlikely(Rc(ctx->opcode) != 0))
1045
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1046
}
1047

    
1048
/* mulhwu  mulhwu.  */
1049
static void gen_mulhwu(DisasContext *ctx)
1050
{
1051
    TCGv_i64 t0, t1;
1052

    
1053
    t0 = tcg_temp_new_i64();
1054
    t1 = tcg_temp_new_i64();
1055
#if defined(TARGET_PPC64)
1056
    tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1057
    tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1058
    tcg_gen_mul_i64(t0, t0, t1);
1059
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1060
#else
1061
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1062
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1063
    tcg_gen_mul_i64(t0, t0, t1);
1064
    tcg_gen_shri_i64(t0, t0, 32);
1065
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1066
#endif
1067
    tcg_temp_free_i64(t0);
1068
    tcg_temp_free_i64(t1);
1069
    if (unlikely(Rc(ctx->opcode) != 0))
1070
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1071
}
1072

    
1073
/* mullw  mullw. */
1074
static void gen_mullw(DisasContext *ctx)
1075
{
1076
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1077
                   cpu_gpr[rB(ctx->opcode)]);
1078
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1079
    if (unlikely(Rc(ctx->opcode) != 0))
1080
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1081
}
1082

    
1083
/* mullwo  mullwo. */
1084
static void gen_mullwo(DisasContext *ctx)
1085
{
1086
    int l1;
1087
    TCGv_i64 t0, t1;
1088

    
1089
    t0 = tcg_temp_new_i64();
1090
    t1 = tcg_temp_new_i64();
1091
    l1 = gen_new_label();
1092
    /* Start with XER OV disabled, the most likely case */
1093
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1094
#if defined(TARGET_PPC64)
1095
    tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1096
    tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1097
#else
1098
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1099
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1100
#endif
1101
    tcg_gen_mul_i64(t0, t0, t1);
1102
#if defined(TARGET_PPC64)
1103
    tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
1104
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
1105
#else
1106
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1107
    tcg_gen_ext32s_i64(t1, t0);
1108
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
1109
#endif
1110
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1111
    gen_set_label(l1);
1112
    tcg_temp_free_i64(t0);
1113
    tcg_temp_free_i64(t1);
1114
    if (unlikely(Rc(ctx->opcode) != 0))
1115
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1116
}
1117

    
1118
/* mulli */
1119
static void gen_mulli(DisasContext *ctx)
1120
{
1121
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1122
                    SIMM(ctx->opcode));
1123
}
1124
#if defined(TARGET_PPC64)
1125
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
1126
static void glue(gen_, name)(DisasContext *ctx)                                       \
1127
{                                                                             \
1128
    gen_helper_##name (cpu_gpr[rD(ctx->opcode)],                              \
1129
                       cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);   \
1130
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1131
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);                           \
1132
}
1133
/* mulhd  mulhd. */
1134
GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
1135
/* mulhdu  mulhdu. */
1136
GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
1137

    
1138
/* mulld  mulld. */
1139
static void gen_mulld(DisasContext *ctx)
1140
{
1141
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1142
                   cpu_gpr[rB(ctx->opcode)]);
1143
    if (unlikely(Rc(ctx->opcode) != 0))
1144
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1145
}
1146
/* mulldo  mulldo. */
1147
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1148
#endif
1149

    
1150
/* neg neg. nego nego. */
1151
static inline void gen_op_arith_neg(DisasContext *ctx, TCGv ret, TCGv arg1,
1152
                                    int ov_check)
1153
{
1154
    int l1 = gen_new_label();
1155
    int l2 = gen_new_label();
1156
    TCGv t0 = tcg_temp_local_new();
1157
#if defined(TARGET_PPC64)
1158
    if (ctx->sf_mode) {
1159
        tcg_gen_mov_tl(t0, arg1);
1160
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
1161
    } else
1162
#endif
1163
    {
1164
        tcg_gen_ext32s_tl(t0, arg1);
1165
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
1166
    }
1167
    tcg_gen_neg_tl(ret, arg1);
1168
    if (ov_check) {
1169
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1170
    }
1171
    tcg_gen_br(l2);
1172
    gen_set_label(l1);
1173
    tcg_gen_mov_tl(ret, t0);
1174
    if (ov_check) {
1175
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1176
    }
1177
    gen_set_label(l2);
1178
    tcg_temp_free(t0);
1179
    if (unlikely(Rc(ctx->opcode) != 0))
1180
        gen_set_Rc0(ctx, ret);
1181
}
1182

    
1183
static void gen_neg(DisasContext *ctx)
1184
{
1185
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1186
}
1187

    
1188
static void gen_nego(DisasContext *ctx)
1189
{
1190
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1191
}
1192

    
1193
/* Common subf function */
1194
static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
1195
                                     TCGv arg2, int add_ca, int compute_ca,
1196
                                     int compute_ov)
1197
{
1198
    TCGv t0, t1;
1199

    
1200
    if ((!compute_ca && !compute_ov) ||
1201
        (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1202
        t0 = ret;
1203
    } else {
1204
        t0 = tcg_temp_local_new();
1205
    }
1206

    
1207
    if (add_ca) {
1208
        t1 = tcg_temp_local_new();
1209
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
1210
        tcg_gen_shri_tl(t1, t1, XER_CA);
1211
    } else {
1212
        TCGV_UNUSED(t1);
1213
    }
1214

    
1215
    if (compute_ca && compute_ov) {
1216
        /* Start with XER CA and OV disabled, the most likely case */
1217
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
1218
    } else if (compute_ca) {
1219
        /* Start with XER CA disabled, the most likely case */
1220
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1221
    } else if (compute_ov) {
1222
        /* Start with XER OV disabled, the most likely case */
1223
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1224
    }
1225

    
1226
    if (add_ca) {
1227
        tcg_gen_not_tl(t0, arg1);
1228
        tcg_gen_add_tl(t0, t0, arg2);
1229
        gen_op_arith_compute_ca(ctx, t0, arg2, 0);
1230
        tcg_gen_add_tl(t0, t0, t1);
1231
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
1232
        tcg_temp_free(t1);
1233
    } else {
1234
        tcg_gen_sub_tl(t0, arg2, arg1);
1235
        if (compute_ca) {
1236
            gen_op_arith_compute_ca(ctx, t0, arg2, 1);
1237
        }
1238
    }
1239
    if (compute_ov) {
1240
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1241
    }
1242

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

    
1246
    if (!TCGV_EQUAL(t0, ret)) {
1247
        tcg_gen_mov_tl(ret, t0);
1248
        tcg_temp_free(t0);
1249
    }
1250
}
1251
/* Sub functions with Two operands functions */
1252
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
1253
static void glue(gen_, name)(DisasContext *ctx)                                       \
1254
{                                                                             \
1255
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1256
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1257
                      add_ca, compute_ca, compute_ov);                        \
1258
}
1259
/* Sub functions with one operand and one immediate */
1260
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
1261
                                add_ca, compute_ca, compute_ov)               \
1262
static void glue(gen_, name)(DisasContext *ctx)                                       \
1263
{                                                                             \
1264
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
1265
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1266
                      cpu_gpr[rA(ctx->opcode)], t0,                           \
1267
                      add_ca, compute_ca, compute_ov);                        \
1268
    tcg_temp_free(t0);                                                        \
1269
}
1270
/* subf  subf.  subfo  subfo. */
1271
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1272
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1273
/* subfc  subfc.  subfco  subfco. */
1274
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1275
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1276
/* subfe  subfe.  subfeo  subfo. */
1277
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1278
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1279
/* subfme  subfme.  subfmeo  subfmeo.  */
1280
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1281
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1282
/* subfze  subfze.  subfzeo  subfzeo.*/
1283
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1284
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
1285

    
1286
/* subfic */
1287
static void gen_subfic(DisasContext *ctx)
1288
{
1289
    /* Start with XER CA and OV disabled, the most likely case */
1290
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1291
    TCGv t0 = tcg_temp_local_new();
1292
    TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
1293
    tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
1294
    gen_op_arith_compute_ca(ctx, t0, t1, 1);
1295
    tcg_temp_free(t1);
1296
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
1297
    tcg_temp_free(t0);
1298
}
1299

    
1300
/***                            Integer logical                            ***/
1301
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
1302
static void glue(gen_, name)(DisasContext *ctx)                                       \
1303
{                                                                             \
1304
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
1305
       cpu_gpr[rB(ctx->opcode)]);                                             \
1306
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1307
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1308
}
1309

    
1310
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
1311
static void glue(gen_, name)(DisasContext *ctx)                                       \
1312
{                                                                             \
1313
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1314
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1315
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1316
}
1317

    
1318
/* and & and. */
1319
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
1320
/* andc & andc. */
1321
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
1322

    
1323
/* andi. */
1324
static void gen_andi_(DisasContext *ctx)
1325
{
1326
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1327
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1328
}
1329

    
1330
/* andis. */
1331
static void gen_andis_(DisasContext *ctx)
1332
{
1333
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1334
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1335
}
1336

    
1337
/* cntlzw */
1338
static void gen_cntlzw(DisasContext *ctx)
1339
{
1340
    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1341
    if (unlikely(Rc(ctx->opcode) != 0))
1342
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1343
}
1344
/* eqv & eqv. */
1345
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
1346
/* extsb & extsb. */
1347
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
1348
/* extsh & extsh. */
1349
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
1350
/* nand & nand. */
1351
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
1352
/* nor & nor. */
1353
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
1354

    
1355
/* or & or. */
1356
static void gen_or(DisasContext *ctx)
1357
{
1358
    int rs, ra, rb;
1359

    
1360
    rs = rS(ctx->opcode);
1361
    ra = rA(ctx->opcode);
1362
    rb = rB(ctx->opcode);
1363
    /* Optimisation for mr. ri case */
1364
    if (rs != ra || rs != rb) {
1365
        if (rs != rb)
1366
            tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1367
        else
1368
            tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
1369
        if (unlikely(Rc(ctx->opcode) != 0))
1370
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1371
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1372
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1373
#if defined(TARGET_PPC64)
1374
    } else {
1375
        int prio = 0;
1376

    
1377
        switch (rs) {
1378
        case 1:
1379
            /* Set process priority to low */
1380
            prio = 2;
1381
            break;
1382
        case 6:
1383
            /* Set process priority to medium-low */
1384
            prio = 3;
1385
            break;
1386
        case 2:
1387
            /* Set process priority to normal */
1388
            prio = 4;
1389
            break;
1390
#if !defined(CONFIG_USER_ONLY)
1391
        case 31:
1392
            if (ctx->mem_idx > 0) {
1393
                /* Set process priority to very low */
1394
                prio = 1;
1395
            }
1396
            break;
1397
        case 5:
1398
            if (ctx->mem_idx > 0) {
1399
                /* Set process priority to medium-hight */
1400
                prio = 5;
1401
            }
1402
            break;
1403
        case 3:
1404
            if (ctx->mem_idx > 0) {
1405
                /* Set process priority to high */
1406
                prio = 6;
1407
            }
1408
            break;
1409
        case 7:
1410
            if (ctx->mem_idx > 1) {
1411
                /* Set process priority to very high */
1412
                prio = 7;
1413
            }
1414
            break;
1415
#endif
1416
        default:
1417
            /* nop */
1418
            break;
1419
        }
1420
        if (prio) {
1421
            TCGv t0 = tcg_temp_new();
1422
            gen_load_spr(t0, SPR_PPR);
1423
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1424
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1425
            gen_store_spr(SPR_PPR, t0);
1426
            tcg_temp_free(t0);
1427
        }
1428
#endif
1429
    }
1430
}
1431
/* orc & orc. */
1432
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
1433

    
1434
/* xor & xor. */
1435
static void gen_xor(DisasContext *ctx)
1436
{
1437
    /* Optimisation for "set to zero" case */
1438
    if (rS(ctx->opcode) != rB(ctx->opcode))
1439
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1440
    else
1441
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1442
    if (unlikely(Rc(ctx->opcode) != 0))
1443
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1444
}
1445

    
1446
/* ori */
1447
static void gen_ori(DisasContext *ctx)
1448
{
1449
    target_ulong uimm = UIMM(ctx->opcode);
1450

    
1451
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1452
        /* NOP */
1453
        /* XXX: should handle special NOPs for POWER series */
1454
        return;
1455
    }
1456
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1457
}
1458

    
1459
/* oris */
1460
static void gen_oris(DisasContext *ctx)
1461
{
1462
    target_ulong uimm = UIMM(ctx->opcode);
1463

    
1464
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1465
        /* NOP */
1466
        return;
1467
    }
1468
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1469
}
1470

    
1471
/* xori */
1472
static void gen_xori(DisasContext *ctx)
1473
{
1474
    target_ulong uimm = UIMM(ctx->opcode);
1475

    
1476
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1477
        /* NOP */
1478
        return;
1479
    }
1480
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1481
}
1482

    
1483
/* xoris */
1484
static void gen_xoris(DisasContext *ctx)
1485
{
1486
    target_ulong uimm = UIMM(ctx->opcode);
1487

    
1488
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1489
        /* NOP */
1490
        return;
1491
    }
1492
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1493
}
1494

    
1495
/* popcntb : PowerPC 2.03 specification */
1496
static void gen_popcntb(DisasContext *ctx)
1497
{
1498
    gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1499
}
1500

    
1501
static void gen_popcntw(DisasContext *ctx)
1502
{
1503
    gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1504
}
1505

    
1506
#if defined(TARGET_PPC64)
1507
/* popcntd: PowerPC 2.06 specification */
1508
static void gen_popcntd(DisasContext *ctx)
1509
{
1510
    gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1511
}
1512
#endif
1513

    
1514
#if defined(TARGET_PPC64)
1515
/* extsw & extsw. */
1516
GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1517

    
1518
/* cntlzd */
1519
static void gen_cntlzd(DisasContext *ctx)
1520
{
1521
    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1522
    if (unlikely(Rc(ctx->opcode) != 0))
1523
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1524
}
1525
#endif
1526

    
1527
/***                             Integer rotate                            ***/
1528

    
1529
/* rlwimi & rlwimi. */
1530
static void gen_rlwimi(DisasContext *ctx)
1531
{
1532
    uint32_t mb, me, sh;
1533

    
1534
    mb = MB(ctx->opcode);
1535
    me = ME(ctx->opcode);
1536
    sh = SH(ctx->opcode);
1537
    if (likely(sh == 0 && mb == 0 && me == 31)) {
1538
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1539
    } else {
1540
        target_ulong mask;
1541
        TCGv t1;
1542
        TCGv t0 = tcg_temp_new();
1543
#if defined(TARGET_PPC64)
1544
        TCGv_i32 t2 = tcg_temp_new_i32();
1545
        tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
1546
        tcg_gen_rotli_i32(t2, t2, sh);
1547
        tcg_gen_extu_i32_i64(t0, t2);
1548
        tcg_temp_free_i32(t2);
1549
#else
1550
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1551
#endif
1552
#if defined(TARGET_PPC64)
1553
        mb += 32;
1554
        me += 32;
1555
#endif
1556
        mask = MASK(mb, me);
1557
        t1 = tcg_temp_new();
1558
        tcg_gen_andi_tl(t0, t0, mask);
1559
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1560
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1561
        tcg_temp_free(t0);
1562
        tcg_temp_free(t1);
1563
    }
1564
    if (unlikely(Rc(ctx->opcode) != 0))
1565
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1566
}
1567

    
1568
/* rlwinm & rlwinm. */
1569
static void gen_rlwinm(DisasContext *ctx)
1570
{
1571
    uint32_t mb, me, sh;
1572

    
1573
    sh = SH(ctx->opcode);
1574
    mb = MB(ctx->opcode);
1575
    me = ME(ctx->opcode);
1576

    
1577
    if (likely(mb == 0 && me == (31 - sh))) {
1578
        if (likely(sh == 0)) {
1579
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1580
        } else {
1581
            TCGv t0 = tcg_temp_new();
1582
            tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1583
            tcg_gen_shli_tl(t0, t0, sh);
1584
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1585
            tcg_temp_free(t0);
1586
        }
1587
    } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
1588
        TCGv t0 = tcg_temp_new();
1589
        tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1590
        tcg_gen_shri_tl(t0, t0, mb);
1591
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1592
        tcg_temp_free(t0);
1593
    } else {
1594
        TCGv t0 = tcg_temp_new();
1595
#if defined(TARGET_PPC64)
1596
        TCGv_i32 t1 = tcg_temp_new_i32();
1597
        tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1598
        tcg_gen_rotli_i32(t1, t1, sh);
1599
        tcg_gen_extu_i32_i64(t0, t1);
1600
        tcg_temp_free_i32(t1);
1601
#else
1602
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1603
#endif
1604
#if defined(TARGET_PPC64)
1605
        mb += 32;
1606
        me += 32;
1607
#endif
1608
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1609
        tcg_temp_free(t0);
1610
    }
1611
    if (unlikely(Rc(ctx->opcode) != 0))
1612
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1613
}
1614

    
1615
/* rlwnm & rlwnm. */
1616
static void gen_rlwnm(DisasContext *ctx)
1617
{
1618
    uint32_t mb, me;
1619
    TCGv t0;
1620
#if defined(TARGET_PPC64)
1621
    TCGv_i32 t1, t2;
1622
#endif
1623

    
1624
    mb = MB(ctx->opcode);
1625
    me = ME(ctx->opcode);
1626
    t0 = tcg_temp_new();
1627
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1628
#if defined(TARGET_PPC64)
1629
    t1 = tcg_temp_new_i32();
1630
    t2 = tcg_temp_new_i32();
1631
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1632
    tcg_gen_trunc_i64_i32(t2, t0);
1633
    tcg_gen_rotl_i32(t1, t1, t2);
1634
    tcg_gen_extu_i32_i64(t0, t1);
1635
    tcg_temp_free_i32(t1);
1636
    tcg_temp_free_i32(t2);
1637
#else
1638
    tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
1639
#endif
1640
    if (unlikely(mb != 0 || me != 31)) {
1641
#if defined(TARGET_PPC64)
1642
        mb += 32;
1643
        me += 32;
1644
#endif
1645
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1646
    } else {
1647
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1648
    }
1649
    tcg_temp_free(t0);
1650
    if (unlikely(Rc(ctx->opcode) != 0))
1651
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1652
}
1653

    
1654
#if defined(TARGET_PPC64)
1655
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
1656
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1657
{                                                                             \
1658
    gen_##name(ctx, 0);                                                       \
1659
}                                                                             \
1660
                                                                              \
1661
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1662
{                                                                             \
1663
    gen_##name(ctx, 1);                                                       \
1664
}
1665
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
1666
static void glue(gen_, name##0)(DisasContext *ctx)                            \
1667
{                                                                             \
1668
    gen_##name(ctx, 0, 0);                                                    \
1669
}                                                                             \
1670
                                                                              \
1671
static void glue(gen_, name##1)(DisasContext *ctx)                            \
1672
{                                                                             \
1673
    gen_##name(ctx, 0, 1);                                                    \
1674
}                                                                             \
1675
                                                                              \
1676
static void glue(gen_, name##2)(DisasContext *ctx)                            \
1677
{                                                                             \
1678
    gen_##name(ctx, 1, 0);                                                    \
1679
}                                                                             \
1680
                                                                              \
1681
static void glue(gen_, name##3)(DisasContext *ctx)                            \
1682
{                                                                             \
1683
    gen_##name(ctx, 1, 1);                                                    \
1684
}
1685

    
1686
static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
1687
                              uint32_t sh)
1688
{
1689
    if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
1690
        tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1691
    } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
1692
        tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
1693
    } else {
1694
        TCGv t0 = tcg_temp_new();
1695
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1696
        if (likely(mb == 0 && me == 63)) {
1697
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1698
        } else {
1699
            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1700
        }
1701
        tcg_temp_free(t0);
1702
    }
1703
    if (unlikely(Rc(ctx->opcode) != 0))
1704
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1705
}
1706
/* rldicl - rldicl. */
1707
static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
1708
{
1709
    uint32_t sh, mb;
1710

    
1711
    sh = SH(ctx->opcode) | (shn << 5);
1712
    mb = MB(ctx->opcode) | (mbn << 5);
1713
    gen_rldinm(ctx, mb, 63, sh);
1714
}
1715
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1716
/* rldicr - rldicr. */
1717
static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
1718
{
1719
    uint32_t sh, me;
1720

    
1721
    sh = SH(ctx->opcode) | (shn << 5);
1722
    me = MB(ctx->opcode) | (men << 5);
1723
    gen_rldinm(ctx, 0, me, sh);
1724
}
1725
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1726
/* rldic - rldic. */
1727
static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
1728
{
1729
    uint32_t sh, mb;
1730

    
1731
    sh = SH(ctx->opcode) | (shn << 5);
1732
    mb = MB(ctx->opcode) | (mbn << 5);
1733
    gen_rldinm(ctx, mb, 63 - sh, sh);
1734
}
1735
GEN_PPC64_R4(rldic, 0x1E, 0x04);
1736

    
1737
static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
1738
{
1739
    TCGv t0;
1740

    
1741
    mb = MB(ctx->opcode);
1742
    me = ME(ctx->opcode);
1743
    t0 = tcg_temp_new();
1744
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1745
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1746
    if (unlikely(mb != 0 || me != 63)) {
1747
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1748
    } else {
1749
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1750
    }
1751
    tcg_temp_free(t0);
1752
    if (unlikely(Rc(ctx->opcode) != 0))
1753
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1754
}
1755

    
1756
/* rldcl - rldcl. */
1757
static inline void gen_rldcl(DisasContext *ctx, int mbn)
1758
{
1759
    uint32_t mb;
1760

    
1761
    mb = MB(ctx->opcode) | (mbn << 5);
1762
    gen_rldnm(ctx, mb, 63);
1763
}
1764
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1765
/* rldcr - rldcr. */
1766
static inline void gen_rldcr(DisasContext *ctx, int men)
1767
{
1768
    uint32_t me;
1769

    
1770
    me = MB(ctx->opcode) | (men << 5);
1771
    gen_rldnm(ctx, 0, me);
1772
}
1773
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1774
/* rldimi - rldimi. */
1775
static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
1776
{
1777
    uint32_t sh, mb, me;
1778

    
1779
    sh = SH(ctx->opcode) | (shn << 5);
1780
    mb = MB(ctx->opcode) | (mbn << 5);
1781
    me = 63 - sh;
1782
    if (unlikely(sh == 0 && mb == 0)) {
1783
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1784
    } else {
1785
        TCGv t0, t1;
1786
        target_ulong mask;
1787

    
1788
        t0 = tcg_temp_new();
1789
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1790
        t1 = tcg_temp_new();
1791
        mask = MASK(mb, me);
1792
        tcg_gen_andi_tl(t0, t0, mask);
1793
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1794
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1795
        tcg_temp_free(t0);
1796
        tcg_temp_free(t1);
1797
    }
1798
    if (unlikely(Rc(ctx->opcode) != 0))
1799
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1800
}
1801
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1802
#endif
1803

    
1804
/***                             Integer shift                             ***/
1805

    
1806
/* slw & slw. */
1807
static void gen_slw(DisasContext *ctx)
1808
{
1809
    TCGv t0, t1;
1810

    
1811
    t0 = tcg_temp_new();
1812
    /* AND rS with a mask that is 0 when rB >= 0x20 */
1813
#if defined(TARGET_PPC64)
1814
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1815
    tcg_gen_sari_tl(t0, t0, 0x3f);
1816
#else
1817
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1818
    tcg_gen_sari_tl(t0, t0, 0x1f);
1819
#endif
1820
    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1821
    t1 = tcg_temp_new();
1822
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1823
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1824
    tcg_temp_free(t1);
1825
    tcg_temp_free(t0);
1826
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1827
    if (unlikely(Rc(ctx->opcode) != 0))
1828
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1829
}
1830

    
1831
/* sraw & sraw. */
1832
static void gen_sraw(DisasContext *ctx)
1833
{
1834
    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)],
1835
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1836
    if (unlikely(Rc(ctx->opcode) != 0))
1837
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1838
}
1839

    
1840
/* srawi & srawi. */
1841
static void gen_srawi(DisasContext *ctx)
1842
{
1843
    int sh = SH(ctx->opcode);
1844
    if (sh != 0) {
1845
        int l1, l2;
1846
        TCGv t0;
1847
        l1 = gen_new_label();
1848
        l2 = gen_new_label();
1849
        t0 = tcg_temp_local_new();
1850
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1851
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
1852
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1853
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1854
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1855
        tcg_gen_br(l2);
1856
        gen_set_label(l1);
1857
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1858
        gen_set_label(l2);
1859
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1860
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
1861
        tcg_temp_free(t0);
1862
    } else {
1863
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1864
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1865
    }
1866
    if (unlikely(Rc(ctx->opcode) != 0))
1867
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1868
}
1869

    
1870
/* srw & srw. */
1871
static void gen_srw(DisasContext *ctx)
1872
{
1873
    TCGv t0, t1;
1874

    
1875
    t0 = tcg_temp_new();
1876
    /* AND rS with a mask that is 0 when rB >= 0x20 */
1877
#if defined(TARGET_PPC64)
1878
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1879
    tcg_gen_sari_tl(t0, t0, 0x3f);
1880
#else
1881
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1882
    tcg_gen_sari_tl(t0, t0, 0x1f);
1883
#endif
1884
    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1885
    tcg_gen_ext32u_tl(t0, t0);
1886
    t1 = tcg_temp_new();
1887
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1888
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1889
    tcg_temp_free(t1);
1890
    tcg_temp_free(t0);
1891
    if (unlikely(Rc(ctx->opcode) != 0))
1892
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1893
}
1894

    
1895
#if defined(TARGET_PPC64)
1896
/* sld & sld. */
1897
static void gen_sld(DisasContext *ctx)
1898
{
1899
    TCGv t0, t1;
1900

    
1901
    t0 = tcg_temp_new();
1902
    /* AND rS with a mask that is 0 when rB >= 0x40 */
1903
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1904
    tcg_gen_sari_tl(t0, t0, 0x3f);
1905
    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1906
    t1 = tcg_temp_new();
1907
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
1908
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1909
    tcg_temp_free(t1);
1910
    tcg_temp_free(t0);
1911
    if (unlikely(Rc(ctx->opcode) != 0))
1912
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1913
}
1914

    
1915
/* srad & srad. */
1916
static void gen_srad(DisasContext *ctx)
1917
{
1918
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
1919
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1920
    if (unlikely(Rc(ctx->opcode) != 0))
1921
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1922
}
1923
/* sradi & sradi. */
1924
static inline void gen_sradi(DisasContext *ctx, int n)
1925
{
1926
    int sh = SH(ctx->opcode) + (n << 5);
1927
    if (sh != 0) {
1928
        int l1, l2;
1929
        TCGv t0;
1930
        l1 = gen_new_label();
1931
        l2 = gen_new_label();
1932
        t0 = tcg_temp_local_new();
1933
        tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
1934
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1935
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1936
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1937
        tcg_gen_br(l2);
1938
        gen_set_label(l1);
1939
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1940
        gen_set_label(l2);
1941
        tcg_temp_free(t0);
1942
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1943
    } else {
1944
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1945
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1946
    }
1947
    if (unlikely(Rc(ctx->opcode) != 0))
1948
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1949
}
1950

    
1951
static void gen_sradi0(DisasContext *ctx)
1952
{
1953
    gen_sradi(ctx, 0);
1954
}
1955

    
1956
static void gen_sradi1(DisasContext *ctx)
1957
{
1958
    gen_sradi(ctx, 1);
1959
}
1960

    
1961
/* srd & srd. */
1962
static void gen_srd(DisasContext *ctx)
1963
{
1964
    TCGv t0, t1;
1965

    
1966
    t0 = tcg_temp_new();
1967
    /* AND rS with a mask that is 0 when rB >= 0x40 */
1968
    tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1969
    tcg_gen_sari_tl(t0, t0, 0x3f);
1970
    tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1971
    t1 = tcg_temp_new();
1972
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
1973
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1974
    tcg_temp_free(t1);
1975
    tcg_temp_free(t0);
1976
    if (unlikely(Rc(ctx->opcode) != 0))
1977
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1978
}
1979
#endif
1980

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

    
2001
#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
2002
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
2003
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
2004

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

    
2027
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2028
static void gen_f##name(DisasContext *ctx)                                    \
2029
{                                                                             \
2030
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2031
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2032
        return;                                                               \
2033
    }                                                                         \
2034
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2035
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2036
    gen_reset_fpstatus();                                                     \
2037
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
2038
                       cpu_fpr[rC(ctx->opcode)]);                             \
2039
    if (isfloat) {                                                            \
2040
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2041
    }                                                                         \
2042
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2043
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2044
}
2045
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
2046
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2047
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2048

    
2049
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2050
static void gen_f##name(DisasContext *ctx)                                    \
2051
{                                                                             \
2052
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2053
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2054
        return;                                                               \
2055
    }                                                                         \
2056
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2057
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2058
    gen_reset_fpstatus();                                                     \
2059
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2060
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2061
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2062
}
2063

    
2064
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2065
static void gen_f##name(DisasContext *ctx)                                    \
2066
{                                                                             \
2067
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2068
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
2069
        return;                                                               \
2070
    }                                                                         \
2071
    /* NIP cannot be restored if the memory exception comes from an helper */ \
2072
    gen_update_nip(ctx, ctx->nip - 4);                                        \
2073
    gen_reset_fpstatus();                                                     \
2074
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2075
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2076
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2077
}
2078

    
2079
/* fadd - fadds */
2080
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2081
/* fdiv - fdivs */
2082
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2083
/* fmul - fmuls */
2084
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
2085

    
2086
/* fre */
2087
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2088

    
2089
/* fres */
2090
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
2091

    
2092
/* frsqrte */
2093
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2094

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

    
2110
/* fsel */
2111
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2112
/* fsub - fsubs */
2113
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
2114
/* Optional: */
2115

    
2116
/* fsqrt */
2117
static void gen_fsqrt(DisasContext *ctx)
2118
{
2119
    if (unlikely(!ctx->fpu_enabled)) {
2120
        gen_exception(ctx, POWERPC_EXCP_FPU);
2121
        return;
2122
    }
2123
    /* NIP cannot be restored if the memory exception comes from an helper */
2124
    gen_update_nip(ctx, ctx->nip - 4);
2125
    gen_reset_fpstatus();
2126
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2127
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2128
}
2129

    
2130
static void gen_fsqrts(DisasContext *ctx)
2131
{
2132
    if (unlikely(!ctx->fpu_enabled)) {
2133
        gen_exception(ctx, POWERPC_EXCP_FPU);
2134
        return;
2135
    }
2136
    /* NIP cannot be restored if the memory exception comes from an helper */
2137
    gen_update_nip(ctx, ctx->nip - 4);
2138
    gen_reset_fpstatus();
2139
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2140
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2141
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2142
}
2143

    
2144
/***                     Floating-Point multiply-and-add                   ***/
2145
/* fmadd - fmadds */
2146
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2147
/* fmsub - fmsubs */
2148
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2149
/* fnmadd - fnmadds */
2150
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2151
/* fnmsub - fnmsubs */
2152
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
2153

    
2154
/***                     Floating-Point round & convert                    ***/
2155
/* fctiw */
2156
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
2157
/* fctiwz */
2158
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
2159
/* frsp */
2160
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
2161
#if defined(TARGET_PPC64)
2162
/* fcfid */
2163
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
2164
/* fctid */
2165
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
2166
/* fctidz */
2167
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
2168
#endif
2169

    
2170
/* frin */
2171
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2172
/* friz */
2173
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2174
/* frip */
2175
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2176
/* frim */
2177
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2178

    
2179
/***                         Floating-Point compare                        ***/
2180

    
2181
/* fcmpo */
2182
static void gen_fcmpo(DisasContext *ctx)
2183
{
2184
    TCGv_i32 crf;
2185
    if (unlikely(!ctx->fpu_enabled)) {
2186
        gen_exception(ctx, POWERPC_EXCP_FPU);
2187
        return;
2188
    }
2189
    /* NIP cannot be restored if the memory exception comes from an helper */
2190
    gen_update_nip(ctx, ctx->nip - 4);
2191
    gen_reset_fpstatus();
2192
    crf = tcg_const_i32(crfD(ctx->opcode));
2193
    gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2194
    tcg_temp_free_i32(crf);
2195
    gen_helper_float_check_status();
2196
}
2197

    
2198
/* fcmpu */
2199
static void gen_fcmpu(DisasContext *ctx)
2200
{
2201
    TCGv_i32 crf;
2202
    if (unlikely(!ctx->fpu_enabled)) {
2203
        gen_exception(ctx, POWERPC_EXCP_FPU);
2204
        return;
2205
    }
2206
    /* NIP cannot be restored if the memory exception comes from an helper */
2207
    gen_update_nip(ctx, ctx->nip - 4);
2208
    gen_reset_fpstatus();
2209
    crf = tcg_const_i32(crfD(ctx->opcode));
2210
    gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
2211
    tcg_temp_free_i32(crf);
2212
    gen_helper_float_check_status();
2213
}
2214

    
2215
/***                         Floating-point move                           ***/
2216
/* fabs */
2217
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2218
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2219

    
2220
/* fmr  - fmr. */
2221
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2222
static void gen_fmr(DisasContext *ctx)
2223
{
2224
    if (unlikely(!ctx->fpu_enabled)) {
2225
        gen_exception(ctx, POWERPC_EXCP_FPU);
2226
        return;
2227
    }
2228
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2229
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2230
}
2231

    
2232
/* fnabs */
2233
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2234
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2235
/* fneg */
2236
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2237
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2238

    
2239
/***                  Floating-Point status & ctrl register                ***/
2240

    
2241
/* mcrfs */
2242
static void gen_mcrfs(DisasContext *ctx)
2243
{
2244
    int bfa;
2245

    
2246
    if (unlikely(!ctx->fpu_enabled)) {
2247
        gen_exception(ctx, POWERPC_EXCP_FPU);
2248
        return;
2249
    }
2250
    bfa = 4 * (7 - crfS(ctx->opcode));
2251
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
2252
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2253
    tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
2254
}
2255

    
2256
/* mffs */
2257
static void gen_mffs(DisasContext *ctx)
2258
{
2259
    if (unlikely(!ctx->fpu_enabled)) {
2260
        gen_exception(ctx, POWERPC_EXCP_FPU);
2261
        return;
2262
    }
2263
    gen_reset_fpstatus();
2264
    tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2265
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2266
}
2267

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

    
2273
    if (unlikely(!ctx->fpu_enabled)) {
2274
        gen_exception(ctx, POWERPC_EXCP_FPU);
2275
        return;
2276
    }
2277
    crb = 31 - crbD(ctx->opcode);
2278
    gen_reset_fpstatus();
2279
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
2280
        TCGv_i32 t0;
2281
        /* NIP cannot be restored if the memory exception comes from an helper */
2282
        gen_update_nip(ctx, ctx->nip - 4);
2283
        t0 = tcg_const_i32(crb);
2284
        gen_helper_fpscr_clrbit(t0);
2285
        tcg_temp_free_i32(t0);
2286
    }
2287
    if (unlikely(Rc(ctx->opcode) != 0)) {
2288
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2289
    }
2290
}
2291

    
2292
/* mtfsb1 */
2293
static void gen_mtfsb1(DisasContext *ctx)
2294
{
2295
    uint8_t crb;
2296

    
2297
    if (unlikely(!ctx->fpu_enabled)) {
2298
        gen_exception(ctx, POWERPC_EXCP_FPU);
2299
        return;
2300
    }
2301
    crb = 31 - crbD(ctx->opcode);
2302
    gen_reset_fpstatus();
2303
    /* XXX: we pretend we can only do IEEE floating-point computations */
2304
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2305
        TCGv_i32 t0;
2306
        /* NIP cannot be restored if the memory exception comes from an helper */
2307
        gen_update_nip(ctx, ctx->nip - 4);
2308
        t0 = tcg_const_i32(crb);
2309
        gen_helper_fpscr_setbit(t0);
2310
        tcg_temp_free_i32(t0);
2311
    }
2312
    if (unlikely(Rc(ctx->opcode) != 0)) {
2313
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2314
    }
2315
    /* We can raise a differed exception */
2316
    gen_helper_float_check_status();
2317
}
2318

    
2319
/* mtfsf */
2320
static void gen_mtfsf(DisasContext *ctx)
2321
{
2322
    TCGv_i32 t0;
2323
    int L = ctx->opcode & 0x02000000;
2324

    
2325
    if (unlikely(!ctx->fpu_enabled)) {
2326
        gen_exception(ctx, POWERPC_EXCP_FPU);
2327
        return;
2328
    }
2329
    /* NIP cannot be restored if the memory exception comes from an helper */
2330
    gen_update_nip(ctx, ctx->nip - 4);
2331
    gen_reset_fpstatus();
2332
    if (L)
2333
        t0 = tcg_const_i32(0xff);
2334
    else
2335
        t0 = tcg_const_i32(FM(ctx->opcode));
2336
    gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
2337
    tcg_temp_free_i32(t0);
2338
    if (unlikely(Rc(ctx->opcode) != 0)) {
2339
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2340
    }
2341
    /* We can raise a differed exception */
2342
    gen_helper_float_check_status();
2343
}
2344

    
2345
/* mtfsfi */
2346
static void gen_mtfsfi(DisasContext *ctx)
2347
{
2348
    int bf, sh;
2349
    TCGv_i64 t0;
2350
    TCGv_i32 t1;
2351

    
2352
    if (unlikely(!ctx->fpu_enabled)) {
2353
        gen_exception(ctx, POWERPC_EXCP_FPU);
2354
        return;
2355
    }
2356
    bf = crbD(ctx->opcode) >> 2;
2357
    sh = 7 - bf;
2358
    /* NIP cannot be restored if the memory exception comes from an helper */
2359
    gen_update_nip(ctx, ctx->nip - 4);
2360
    gen_reset_fpstatus();
2361
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
2362
    t1 = tcg_const_i32(1 << sh);
2363
    gen_helper_store_fpscr(t0, t1);
2364
    tcg_temp_free_i64(t0);
2365
    tcg_temp_free_i32(t1);
2366
    if (unlikely(Rc(ctx->opcode) != 0)) {
2367
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2368
    }
2369
    /* We can raise a differed exception */
2370
    gen_helper_float_check_status();
2371
}
2372

    
2373
/***                           Addressing modes                            ***/
2374
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2375
static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
2376
                                      target_long maskl)
2377
{
2378
    target_long simm = SIMM(ctx->opcode);
2379

    
2380
    simm &= ~maskl;
2381
    if (rA(ctx->opcode) == 0) {
2382
#if defined(TARGET_PPC64)
2383
        if (!ctx->sf_mode) {
2384
            tcg_gen_movi_tl(EA, (uint32_t)simm);
2385
        } else
2386
#endif
2387
        tcg_gen_movi_tl(EA, simm);
2388
    } else if (likely(simm != 0)) {
2389
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2390
#if defined(TARGET_PPC64)
2391
        if (!ctx->sf_mode) {
2392
            tcg_gen_ext32u_tl(EA, EA);
2393
        }
2394
#endif
2395
    } else {
2396
#if defined(TARGET_PPC64)
2397
        if (!ctx->sf_mode) {
2398
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2399
        } else
2400
#endif
2401
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2402
    }
2403
}
2404

    
2405
static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
2406
{
2407
    if (rA(ctx->opcode) == 0) {
2408
#if defined(TARGET_PPC64)
2409
        if (!ctx->sf_mode) {
2410
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2411
        } else
2412
#endif
2413
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2414
    } else {
2415
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2416
#if defined(TARGET_PPC64)
2417
        if (!ctx->sf_mode) {
2418
            tcg_gen_ext32u_tl(EA, EA);
2419
        }
2420
#endif
2421
    }
2422
}
2423

    
2424
static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
2425
{
2426
    if (rA(ctx->opcode) == 0) {
2427
        tcg_gen_movi_tl(EA, 0);
2428
    } else {
2429
#if defined(TARGET_PPC64)
2430
        if (!ctx->sf_mode) {
2431
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2432
        } else
2433
#endif
2434
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2435
    }
2436
}
2437

    
2438
static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
2439
                                target_long val)
2440
{
2441
    tcg_gen_addi_tl(ret, arg1, val);
2442
#if defined(TARGET_PPC64)
2443
    if (!ctx->sf_mode) {
2444
        tcg_gen_ext32u_tl(ret, ret);
2445
    }
2446
#endif
2447
}
2448

    
2449
static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
2450
{
2451
    int l1 = gen_new_label();
2452
    TCGv t0 = tcg_temp_new();
2453
    TCGv_i32 t1, t2;
2454
    /* NIP cannot be restored if the memory exception comes from an helper */
2455
    gen_update_nip(ctx, ctx->nip - 4);
2456
    tcg_gen_andi_tl(t0, EA, mask);
2457
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2458
    t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2459
    t2 = tcg_const_i32(0);
2460
    gen_helper_raise_exception_err(t1, t2);
2461
    tcg_temp_free_i32(t1);
2462
    tcg_temp_free_i32(t2);
2463
    gen_set_label(l1);
2464
    tcg_temp_free(t0);
2465
}
2466

    
2467
/***                             Integer load                              ***/
2468
static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2469
{
2470
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2471
}
2472

    
2473
static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2474
{
2475
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
2476
}
2477

    
2478
static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2479
{
2480
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2481
    if (unlikely(ctx->le_mode)) {
2482
        tcg_gen_bswap16_tl(arg1, arg1);
2483
    }
2484
}
2485

    
2486
static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2487
{
2488
    if (unlikely(ctx->le_mode)) {
2489
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2490
        tcg_gen_bswap16_tl(arg1, arg1);
2491
        tcg_gen_ext16s_tl(arg1, arg1);
2492
    } else {
2493
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
2494
    }
2495
}
2496

    
2497
static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2498
{
2499
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2500
    if (unlikely(ctx->le_mode)) {
2501
        tcg_gen_bswap32_tl(arg1, arg1);
2502
    }
2503
}
2504

    
2505
#if defined(TARGET_PPC64)
2506
static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2507
{
2508
    if (unlikely(ctx->le_mode)) {
2509
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2510
        tcg_gen_bswap32_tl(arg1, arg1);
2511
        tcg_gen_ext32s_tl(arg1, arg1);
2512
    } else
2513
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
2514
}
2515
#endif
2516

    
2517
static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2518
{
2519
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
2520
    if (unlikely(ctx->le_mode)) {
2521
        tcg_gen_bswap64_i64(arg1, arg1);
2522
    }
2523
}
2524

    
2525
static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
2526
{
2527
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
2528
}
2529

    
2530
static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
2531
{
2532
    if (unlikely(ctx->le_mode)) {
2533
        TCGv t0 = tcg_temp_new();
2534
        tcg_gen_ext16u_tl(t0, arg1);
2535
        tcg_gen_bswap16_tl(t0, t0);
2536
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2537
        tcg_temp_free(t0);
2538
    } else {
2539
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2540
    }
2541
}
2542

    
2543
static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
2544
{
2545
    if (unlikely(ctx->le_mode)) {
2546
        TCGv t0 = tcg_temp_new();
2547
        tcg_gen_ext32u_tl(t0, arg1);
2548
        tcg_gen_bswap32_tl(t0, t0);
2549
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2550
        tcg_temp_free(t0);
2551
    } else {
2552
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2553
    }
2554
}
2555

    
2556
static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2557
{
2558
    if (unlikely(ctx->le_mode)) {
2559
        TCGv_i64 t0 = tcg_temp_new_i64();
2560
        tcg_gen_bswap64_i64(t0, arg1);
2561
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
2562
        tcg_temp_free_i64(t0);
2563
    } else
2564
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
2565
}
2566

    
2567
#define GEN_LD(name, ldop, opc, type)                                         \
2568
static void glue(gen_, name)(DisasContext *ctx)                                       \
2569
{                                                                             \
2570
    TCGv EA;                                                                  \
2571
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2572
    EA = tcg_temp_new();                                                      \
2573
    gen_addr_imm_index(ctx, EA, 0);                                           \
2574
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2575
    tcg_temp_free(EA);                                                        \
2576
}
2577

    
2578
#define GEN_LDU(name, ldop, opc, type)                                        \
2579
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
2580
{                                                                             \
2581
    TCGv EA;                                                                  \
2582
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2583
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2584
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2585
        return;                                                               \
2586
    }                                                                         \
2587
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2588
    EA = tcg_temp_new();                                                      \
2589
    if (type == PPC_64B)                                                      \
2590
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2591
    else                                                                      \
2592
        gen_addr_imm_index(ctx, EA, 0);                                       \
2593
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2594
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2595
    tcg_temp_free(EA);                                                        \
2596
}
2597

    
2598
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
2599
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
2600
{                                                                             \
2601
    TCGv EA;                                                                  \
2602
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2603
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2604
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2605
        return;                                                               \
2606
    }                                                                         \
2607
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2608
    EA = tcg_temp_new();                                                      \
2609
    gen_addr_reg_index(ctx, EA);                                              \
2610
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2611
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2612
    tcg_temp_free(EA);                                                        \
2613
}
2614

    
2615
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
2616
static void glue(gen_, name##x)(DisasContext *ctx)                            \
2617
{                                                                             \
2618
    TCGv EA;                                                                  \
2619
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2620
    EA = tcg_temp_new();                                                      \
2621
    gen_addr_reg_index(ctx, EA);                                              \
2622
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2623
    tcg_temp_free(EA);                                                        \
2624
}
2625

    
2626
#define GEN_LDS(name, ldop, op, type)                                         \
2627
GEN_LD(name, ldop, op | 0x20, type);                                          \
2628
GEN_LDU(name, ldop, op | 0x21, type);                                         \
2629
GEN_LDUX(name, ldop, 0x17, op | 0x01, type);                                  \
2630
GEN_LDX(name, ldop, 0x17, op | 0x00, type)
2631

    
2632
/* lbz lbzu lbzux lbzx */
2633
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
2634
/* lha lhau lhaux lhax */
2635
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
2636
/* lhz lhzu lhzux lhzx */
2637
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
2638
/* lwz lwzu lwzux lwzx */
2639
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2640
#if defined(TARGET_PPC64)
2641
/* lwaux */
2642
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2643
/* lwax */
2644
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2645
/* ldux */
2646
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2647
/* ldx */
2648
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
2649

    
2650
static void gen_ld(DisasContext *ctx)
2651
{
2652
    TCGv EA;
2653
    if (Rc(ctx->opcode)) {
2654
        if (unlikely(rA(ctx->opcode) == 0 ||
2655
                     rA(ctx->opcode) == rD(ctx->opcode))) {
2656
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2657
            return;
2658
        }
2659
    }
2660
    gen_set_access_type(ctx, ACCESS_INT);
2661
    EA = tcg_temp_new();
2662
    gen_addr_imm_index(ctx, EA, 0x03);
2663
    if (ctx->opcode & 0x02) {
2664
        /* lwa (lwau is undefined) */
2665
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2666
    } else {
2667
        /* ld - ldu */
2668
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2669
    }
2670
    if (Rc(ctx->opcode))
2671
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2672
    tcg_temp_free(EA);
2673
}
2674

    
2675
/* lq */
2676
static void gen_lq(DisasContext *ctx)
2677
{
2678
#if defined(CONFIG_USER_ONLY)
2679
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2680
#else
2681
    int ra, rd;
2682
    TCGv EA;
2683

    
2684
    /* Restore CPU state */
2685
    if (unlikely(ctx->mem_idx == 0)) {
2686
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2687
        return;
2688
    }
2689
    ra = rA(ctx->opcode);
2690
    rd = rD(ctx->opcode);
2691
    if (unlikely((rd & 1) || rd == ra)) {
2692
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2693
        return;
2694
    }
2695
    if (unlikely(ctx->le_mode)) {
2696
        /* Little-endian mode is not handled */
2697
        gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2698
        return;
2699
    }
2700
    gen_set_access_type(ctx, ACCESS_INT);
2701
    EA = tcg_temp_new();
2702
    gen_addr_imm_index(ctx, EA, 0x0F);
2703
    gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2704
    gen_addr_add(ctx, EA, EA, 8);
2705
    gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
2706
    tcg_temp_free(EA);
2707
#endif
2708
}
2709
#endif
2710

    
2711
/***                              Integer store                            ***/
2712
#define GEN_ST(name, stop, opc, type)                                         \
2713
static void glue(gen_, name)(DisasContext *ctx)                                       \
2714
{                                                                             \
2715
    TCGv EA;                                                                  \
2716
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2717
    EA = tcg_temp_new();                                                      \
2718
    gen_addr_imm_index(ctx, EA, 0);                                           \
2719
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2720
    tcg_temp_free(EA);                                                        \
2721
}
2722

    
2723
#define GEN_STU(name, stop, opc, type)                                        \
2724
static void glue(gen_, stop##u)(DisasContext *ctx)                                    \
2725
{                                                                             \
2726
    TCGv EA;                                                                  \
2727
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2728
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2729
        return;                                                               \
2730
    }                                                                         \
2731
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2732
    EA = tcg_temp_new();                                                      \
2733
    if (type == PPC_64B)                                                      \
2734
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2735
    else                                                                      \
2736
        gen_addr_imm_index(ctx, EA, 0);                                       \
2737
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2738
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2739
    tcg_temp_free(EA);                                                        \
2740
}
2741

    
2742
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
2743
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
2744
{                                                                             \
2745
    TCGv EA;                                                                  \
2746
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2747
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
2748
        return;                                                               \
2749
    }                                                                         \
2750
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2751
    EA = tcg_temp_new();                                                      \
2752
    gen_addr_reg_index(ctx, EA);                                              \
2753
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2754
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2755
    tcg_temp_free(EA);                                                        \
2756
}
2757

    
2758
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
2759
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
2760
{                                                                             \
2761
    TCGv EA;                                                                  \
2762
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2763
    EA = tcg_temp_new();                                                      \
2764
    gen_addr_reg_index(ctx, EA);                                              \
2765
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2766
    tcg_temp_free(EA);                                                        \
2767
}
2768

    
2769
#define GEN_STS(name, stop, op, type)                                         \
2770
GEN_ST(name, stop, op | 0x20, type);                                          \
2771
GEN_STU(name, stop, op | 0x21, type);                                         \
2772
GEN_STUX(name, stop, 0x17, op | 0x01, type);                                  \
2773
GEN_STX(name, stop, 0x17, op | 0x00, type)
2774

    
2775
/* stb stbu stbux stbx */
2776
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
2777
/* sth sthu sthux sthx */
2778
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
2779
/* stw stwu stwux stwx */
2780
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2781
#if defined(TARGET_PPC64)
2782
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
2783
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
2784

    
2785
static void gen_std(DisasContext *ctx)
2786
{
2787
    int rs;
2788
    TCGv EA;
2789

    
2790
    rs = rS(ctx->opcode);
2791
    if ((ctx->opcode & 0x3) == 0x2) {
2792
#if defined(CONFIG_USER_ONLY)
2793
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2794
#else
2795
        /* stq */
2796
        if (unlikely(ctx->mem_idx == 0)) {
2797
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
2798
            return;
2799
        }
2800
        if (unlikely(rs & 1)) {
2801
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2802
            return;
2803
        }
2804
        if (unlikely(ctx->le_mode)) {
2805
            /* Little-endian mode is not handled */
2806
            gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2807
            return;
2808
        }
2809
        gen_set_access_type(ctx, ACCESS_INT);
2810
        EA = tcg_temp_new();
2811
        gen_addr_imm_index(ctx, EA, 0x03);
2812
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2813
        gen_addr_add(ctx, EA, EA, 8);
2814
        gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
2815
        tcg_temp_free(EA);
2816
#endif
2817
    } else {
2818
        /* std / stdu */
2819
        if (Rc(ctx->opcode)) {
2820
            if (unlikely(rA(ctx->opcode) == 0)) {
2821
                gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2822
                return;
2823
            }
2824
        }
2825
        gen_set_access_type(ctx, ACCESS_INT);
2826
        EA = tcg_temp_new();
2827
        gen_addr_imm_index(ctx, EA, 0x03);
2828
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2829
        if (Rc(ctx->opcode))
2830
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2831
        tcg_temp_free(EA);
2832
    }
2833
}
2834
#endif
2835
/***                Integer load and store with byte reverse               ***/
2836
/* lhbrx */
2837
static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
2838
{
2839
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2840
    if (likely(!ctx->le_mode)) {
2841
        tcg_gen_bswap16_tl(arg1, arg1);
2842
    }
2843
}
2844
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
2845

    
2846
/* lwbrx */
2847
static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
2848
{
2849
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2850
    if (likely(!ctx->le_mode)) {
2851
        tcg_gen_bswap32_tl(arg1, arg1);
2852
    }
2853
}
2854
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
2855

    
2856
/* sthbrx */
2857
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
2858
{
2859
    if (likely(!ctx->le_mode)) {
2860
        TCGv t0 = tcg_temp_new();
2861
        tcg_gen_ext16u_tl(t0, arg1);
2862
        tcg_gen_bswap16_tl(t0, t0);
2863
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2864
        tcg_temp_free(t0);
2865
    } else {
2866
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2867
    }
2868
}
2869
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
2870

    
2871
/* stwbrx */
2872
static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
2873
{
2874
    if (likely(!ctx->le_mode)) {
2875
        TCGv t0 = tcg_temp_new();
2876
        tcg_gen_ext32u_tl(t0, arg1);
2877
        tcg_gen_bswap32_tl(t0, t0);
2878
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2879
        tcg_temp_free(t0);
2880
    } else {
2881
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2882
    }
2883
}
2884
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
2885

    
2886
/***                    Integer load and store multiple                    ***/
2887

    
2888
/* lmw */
2889
static void gen_lmw(DisasContext *ctx)
2890
{
2891
    TCGv t0;
2892
    TCGv_i32 t1;
2893
    gen_set_access_type(ctx, ACCESS_INT);
2894
    /* NIP cannot be restored if the memory exception comes from an helper */
2895
    gen_update_nip(ctx, ctx->nip - 4);
2896
    t0 = tcg_temp_new();
2897
    t1 = tcg_const_i32(rD(ctx->opcode));
2898
    gen_addr_imm_index(ctx, t0, 0);
2899
    gen_helper_lmw(t0, t1);
2900
    tcg_temp_free(t0);
2901
    tcg_temp_free_i32(t1);
2902
}
2903

    
2904
/* stmw */
2905
static void gen_stmw(DisasContext *ctx)
2906
{
2907
    TCGv t0;
2908
    TCGv_i32 t1;
2909
    gen_set_access_type(ctx, ACCESS_INT);
2910
    /* NIP cannot be restored if the memory exception comes from an helper */
2911
    gen_update_nip(ctx, ctx->nip - 4);
2912
    t0 = tcg_temp_new();
2913
    t1 = tcg_const_i32(rS(ctx->opcode));
2914
    gen_addr_imm_index(ctx, t0, 0);
2915
    gen_helper_stmw(t0, t1);
2916
    tcg_temp_free(t0);
2917
    tcg_temp_free_i32(t1);
2918
}
2919

    
2920
/***                    Integer load and store strings                     ***/
2921

    
2922
/* lswi */
2923
/* PowerPC32 specification says we must generate an exception if
2924
 * rA is in the range of registers to be loaded.
2925
 * In an other hand, IBM says this is valid, but rA won't be loaded.
2926
 * For now, I'll follow the spec...
2927
 */
2928
static void gen_lswi(DisasContext *ctx)
2929
{
2930
    TCGv t0;
2931
    TCGv_i32 t1, t2;
2932
    int nb = NB(ctx->opcode);
2933
    int start = rD(ctx->opcode);
2934
    int ra = rA(ctx->opcode);
2935
    int nr;
2936

    
2937
    if (nb == 0)
2938
        nb = 32;
2939
    nr = nb / 4;
2940
    if (unlikely(((start + nr) > 32  &&
2941
                  start <= ra && (start + nr - 32) > ra) ||
2942
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
2943
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
2944
        return;
2945
    }
2946
    gen_set_access_type(ctx, ACCESS_INT);
2947
    /* NIP cannot be restored if the memory exception comes from an helper */
2948
    gen_update_nip(ctx, ctx->nip - 4);
2949
    t0 = tcg_temp_new();
2950
    gen_addr_register(ctx, t0);
2951
    t1 = tcg_const_i32(nb);
2952
    t2 = tcg_const_i32(start);
2953
    gen_helper_lsw(t0, t1, t2);
2954
    tcg_temp_free(t0);
2955
    tcg_temp_free_i32(t1);
2956
    tcg_temp_free_i32(t2);
2957
}
2958

    
2959
/* lswx */
2960
static void gen_lswx(DisasContext *ctx)
2961
{
2962
    TCGv t0;
2963
    TCGv_i32 t1, t2, t3;
2964
    gen_set_access_type(ctx, ACCESS_INT);
2965
    /* NIP cannot be restored if the memory exception comes from an helper */
2966
    gen_update_nip(ctx, ctx->nip - 4);
2967
    t0 = tcg_temp_new();
2968
    gen_addr_reg_index(ctx, t0);
2969
    t1 = tcg_const_i32(rD(ctx->opcode));
2970
    t2 = tcg_const_i32(rA(ctx->opcode));
2971
    t3 = tcg_const_i32(rB(ctx->opcode));
2972
    gen_helper_lswx(t0, t1, t2, t3);
2973
    tcg_temp_free(t0);
2974
    tcg_temp_free_i32(t1);
2975
    tcg_temp_free_i32(t2);
2976
    tcg_temp_free_i32(t3);
2977
}
2978

    
2979
/* stswi */
2980
static void gen_stswi(DisasContext *ctx)
2981
{
2982
    TCGv t0;
2983
    TCGv_i32 t1, t2;
2984
    int nb = NB(ctx->opcode);
2985
    gen_set_access_type(ctx, ACCESS_INT);
2986
    /* NIP cannot be restored if the memory exception comes from an helper */
2987
    gen_update_nip(ctx, ctx->nip - 4);
2988
    t0 = tcg_temp_new();
2989
    gen_addr_register(ctx, t0);
2990
    if (nb == 0)
2991
        nb = 32;
2992
    t1 = tcg_const_i32(nb);
2993
    t2 = tcg_const_i32(rS(ctx->opcode));
2994
    gen_helper_stsw(t0, t1, t2);
2995
    tcg_temp_free(t0);
2996
    tcg_temp_free_i32(t1);
2997
    tcg_temp_free_i32(t2);
2998
}
2999

    
3000
/* stswx */
3001
static void gen_stswx(DisasContext *ctx)
3002
{
3003
    TCGv t0;
3004
    TCGv_i32 t1, t2;
3005
    gen_set_access_type(ctx, ACCESS_INT);
3006
    /* NIP cannot be restored if the memory exception comes from an helper */
3007
    gen_update_nip(ctx, ctx->nip - 4);
3008
    t0 = tcg_temp_new();
3009
    gen_addr_reg_index(ctx, t0);
3010
    t1 = tcg_temp_new_i32();
3011
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
3012
    tcg_gen_andi_i32(t1, t1, 0x7F);
3013
    t2 = tcg_const_i32(rS(ctx->opcode));
3014
    gen_helper_stsw(t0, t1, t2);
3015
    tcg_temp_free(t0);
3016
    tcg_temp_free_i32(t1);
3017
    tcg_temp_free_i32(t2);
3018
}
3019

    
3020
/***                        Memory synchronisation                         ***/
3021
/* eieio */
3022
static void gen_eieio(DisasContext *ctx)
3023
{
3024
}
3025

    
3026
/* isync */
3027
static void gen_isync(DisasContext *ctx)
3028
{
3029
    gen_stop_exception(ctx);
3030
}
3031

    
3032
/* lwarx */
3033
static void gen_lwarx(DisasContext *ctx)
3034
{
3035
    TCGv t0;
3036
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
3037
    gen_set_access_type(ctx, ACCESS_RES);
3038
    t0 = tcg_temp_local_new();
3039
    gen_addr_reg_index(ctx, t0);
3040
    gen_check_align(ctx, t0, 0x03);
3041
    gen_qemu_ld32u(ctx, gpr, t0);
3042
    tcg_gen_mov_tl(cpu_reserve, t0);
3043
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
3044
    tcg_temp_free(t0);
3045
}
3046

    
3047
#if defined(CONFIG_USER_ONLY)
3048
static void gen_conditional_store (DisasContext *ctx, TCGv EA,
3049
                                   int reg, int size)
3050
{
3051
    TCGv t0 = tcg_temp_new();
3052
    uint32_t save_exception = ctx->exception;
3053

    
3054
    tcg_gen_st_tl(EA, cpu_env, offsetof(CPUState, reserve_ea));
3055
    tcg_gen_movi_tl(t0, (size << 5) | reg);
3056
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, reserve_info));
3057
    tcg_temp_free(t0);
3058
    gen_update_nip(ctx, ctx->nip-4);
3059
    ctx->exception = POWERPC_EXCP_BRANCH;
3060
    gen_exception(ctx, POWERPC_EXCP_STCX);
3061
    ctx->exception = save_exception;
3062
}
3063
#endif
3064

    
3065
/* stwcx. */
3066
static void gen_stwcx_(DisasContext *ctx)
3067
{
3068
    TCGv t0;
3069
    gen_set_access_type(ctx, ACCESS_RES);
3070
    t0 = tcg_temp_local_new();
3071
    gen_addr_reg_index(ctx, t0);
3072
    gen_check_align(ctx, t0, 0x03);
3073
#if defined(CONFIG_USER_ONLY)
3074
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
3075
#else
3076
    {
3077
        int l1;
3078

    
3079
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3080
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3081
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3082
        l1 = gen_new_label();
3083
        tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3084
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3085
        gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3086
        gen_set_label(l1);
3087
        tcg_gen_movi_tl(cpu_reserve, -1);
3088
    }
3089
#endif
3090
    tcg_temp_free(t0);
3091
}
3092

    
3093
#if defined(TARGET_PPC64)
3094
/* ldarx */
3095
static void gen_ldarx(DisasContext *ctx)
3096
{
3097
    TCGv t0;
3098
    TCGv gpr = cpu_gpr[rD(ctx->opcode)];
3099
    gen_set_access_type(ctx, ACCESS_RES);
3100
    t0 = tcg_temp_local_new();
3101
    gen_addr_reg_index(ctx, t0);
3102
    gen_check_align(ctx, t0, 0x07);
3103
    gen_qemu_ld64(ctx, gpr, t0);
3104
    tcg_gen_mov_tl(cpu_reserve, t0);
3105
    tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
3106
    tcg_temp_free(t0);
3107
}
3108

    
3109
/* stdcx. */
3110
static void gen_stdcx_(DisasContext *ctx)
3111
{
3112
    TCGv t0;
3113
    gen_set_access_type(ctx, ACCESS_RES);
3114
    t0 = tcg_temp_local_new();
3115
    gen_addr_reg_index(ctx, t0);
3116
    gen_check_align(ctx, t0, 0x07);
3117
#if defined(CONFIG_USER_ONLY)
3118
    gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
3119
#else
3120
    {
3121
        int l1;
3122
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3123
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3124
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3125
        l1 = gen_new_label();
3126
        tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3127
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3128
        gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3129
        gen_set_label(l1);
3130
        tcg_gen_movi_tl(cpu_reserve, -1);
3131
    }
3132
#endif
3133
    tcg_temp_free(t0);
3134
}
3135
#endif /* defined(TARGET_PPC64) */
3136

    
3137
/* sync */
3138
static void gen_sync(DisasContext *ctx)
3139
{
3140
}
3141

    
3142
/* wait */
3143
static void gen_wait(DisasContext *ctx)
3144
{
3145
    TCGv_i32 t0 = tcg_temp_new_i32();
3146
    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
3147
    tcg_temp_free_i32(t0);
3148
    /* Stop translation, as the CPU is supposed to sleep from now */
3149
    gen_exception_err(ctx, EXCP_HLT, 1);
3150
}
3151

    
3152
/***                         Floating-point load                           ***/
3153
#define GEN_LDF(name, ldop, opc, type)                                        \
3154
static void glue(gen_, name)(DisasContext *ctx)                                       \
3155
{                                                                             \
3156
    TCGv EA;                                                                  \
3157
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3158
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3159
        return;                                                               \
3160
    }                                                                         \
3161
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3162
    EA = tcg_temp_new();                                                      \
3163
    gen_addr_imm_index(ctx, EA, 0);                                           \
3164
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3165
    tcg_temp_free(EA);                                                        \
3166
}
3167

    
3168
#define GEN_LDUF(name, ldop, opc, type)                                       \
3169
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
3170
{                                                                             \
3171
    TCGv EA;                                                                  \
3172
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3173
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3174
        return;                                                               \
3175
    }                                                                         \
3176
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3177
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3178
        return;                                                               \
3179
    }                                                                         \
3180
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3181
    EA = tcg_temp_new();                                                      \
3182
    gen_addr_imm_index(ctx, EA, 0);                                           \
3183
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3184
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3185
    tcg_temp_free(EA);                                                        \
3186
}
3187

    
3188
#define GEN_LDUXF(name, ldop, opc, type)                                      \
3189
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3190
{                                                                             \
3191
    TCGv EA;                                                                  \
3192
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3193
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3194
        return;                                                               \
3195
    }                                                                         \
3196
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3197
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3198
        return;                                                               \
3199
    }                                                                         \
3200
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3201
    EA = tcg_temp_new();                                                      \
3202
    gen_addr_reg_index(ctx, EA);                                              \
3203
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3204
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3205
    tcg_temp_free(EA);                                                        \
3206
}
3207

    
3208
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
3209
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
3210
{                                                                             \
3211
    TCGv EA;                                                                  \
3212
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3213
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3214
        return;                                                               \
3215
    }                                                                         \
3216
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3217
    EA = tcg_temp_new();                                                      \
3218
    gen_addr_reg_index(ctx, EA);                                              \
3219
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3220
    tcg_temp_free(EA);                                                        \
3221
}
3222

    
3223
#define GEN_LDFS(name, ldop, op, type)                                        \
3224
GEN_LDF(name, ldop, op | 0x20, type);                                         \
3225
GEN_LDUF(name, ldop, op | 0x21, type);                                        \
3226
GEN_LDUXF(name, ldop, op | 0x01, type);                                       \
3227
GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3228

    
3229
static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3230
{
3231
    TCGv t0 = tcg_temp_new();
3232
    TCGv_i32 t1 = tcg_temp_new_i32();
3233
    gen_qemu_ld32u(ctx, t0, arg2);
3234
    tcg_gen_trunc_tl_i32(t1, t0);
3235
    tcg_temp_free(t0);
3236
    gen_helper_float32_to_float64(arg1, t1);
3237
    tcg_temp_free_i32(t1);
3238
}
3239

    
3240
 /* lfd lfdu lfdux lfdx */
3241
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3242
 /* lfs lfsu lfsux lfsx */
3243
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
3244

    
3245
/***                         Floating-point store                          ***/
3246
#define GEN_STF(name, stop, opc, type)                                        \
3247
static void glue(gen_, name)(DisasContext *ctx)                                       \
3248
{                                                                             \
3249
    TCGv EA;                                                                  \
3250
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3251
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3252
        return;                                                               \
3253
    }                                                                         \
3254
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3255
    EA = tcg_temp_new();                                                      \
3256
    gen_addr_imm_index(ctx, EA, 0);                                           \
3257
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3258
    tcg_temp_free(EA);                                                        \
3259
}
3260

    
3261
#define GEN_STUF(name, stop, opc, type)                                       \
3262
static void glue(gen_, name##u)(DisasContext *ctx)                                    \
3263
{                                                                             \
3264
    TCGv EA;                                                                  \
3265
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3266
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3267
        return;                                                               \
3268
    }                                                                         \
3269
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3270
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3271
        return;                                                               \
3272
    }                                                                         \
3273
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3274
    EA = tcg_temp_new();                                                      \
3275
    gen_addr_imm_index(ctx, EA, 0);                                           \
3276
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3277
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3278
    tcg_temp_free(EA);                                                        \
3279
}
3280

    
3281
#define GEN_STUXF(name, stop, opc, type)                                      \
3282
static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
3283
{                                                                             \
3284
    TCGv EA;                                                                  \
3285
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3286
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3287
        return;                                                               \
3288
    }                                                                         \
3289
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3290
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
3291
        return;                                                               \
3292
    }                                                                         \
3293
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3294
    EA = tcg_temp_new();                                                      \
3295
    gen_addr_reg_index(ctx, EA);                                              \
3296
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3297
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3298
    tcg_temp_free(EA);                                                        \
3299
}
3300

    
3301
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
3302
static void glue(gen_, name##x)(DisasContext *ctx)                                    \
3303
{                                                                             \
3304
    TCGv EA;                                                                  \
3305
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3306
        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
3307
        return;                                                               \
3308
    }                                                                         \
3309
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3310
    EA = tcg_temp_new();                                                      \
3311
    gen_addr_reg_index(ctx, EA);                                              \
3312
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3313
    tcg_temp_free(EA);                                                        \
3314
}
3315

    
3316
#define GEN_STFS(name, stop, op, type)                                        \
3317
GEN_STF(name, stop, op | 0x20, type);                                         \
3318
GEN_STUF(name, stop, op | 0x21, type);                                        \
3319
GEN_STUXF(name, stop, op | 0x01, type);                                       \
3320
GEN_STXF(name, stop, 0x17, op | 0x00, type)
3321

    
3322
static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3323
{
3324
    TCGv_i32 t0 = tcg_temp_new_i32();
3325
    TCGv t1 = tcg_temp_new();
3326
    gen_helper_float64_to_float32(t0, arg1);
3327
    tcg_gen_extu_i32_tl(t1, t0);
3328
    tcg_temp_free_i32(t0);
3329
    gen_qemu_st32(ctx, t1, arg2);
3330
    tcg_temp_free(t1);
3331
}
3332

    
3333
/* stfd stfdu stfdux stfdx */
3334
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
3335
/* stfs stfsu stfsux stfsx */
3336
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
3337

    
3338
/* Optional: */
3339
static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3340
{
3341
    TCGv t0 = tcg_temp_new();
3342
    tcg_gen_trunc_i64_tl(t0, arg1),
3343
    gen_qemu_st32(ctx, t0, arg2);
3344
    tcg_temp_free(t0);
3345
}
3346
/* stfiwx */
3347
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
3348

    
3349
/***                                Branch                                 ***/
3350
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3351
{
3352
    TranslationBlock *tb;
3353
    tb = ctx->tb;
3354
#if defined(TARGET_PPC64)
3355
    if (!ctx->sf_mode)
3356
        dest = (uint32_t) dest;
3357
#endif
3358
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3359
        likely(!ctx->singlestep_enabled)) {
3360
        tcg_gen_goto_tb(n);
3361
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3362
        tcg_gen_exit_tb((tcg_target_long)tb + n);
3363
    } else {
3364
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3365
        if (unlikely(ctx->singlestep_enabled)) {
3366
            if ((ctx->singlestep_enabled &
3367
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3368
                ctx->exception == POWERPC_EXCP_BRANCH) {
3369
                target_ulong tmp = ctx->nip;
3370
                ctx->nip = dest;
3371
                gen_exception(ctx, POWERPC_EXCP_TRACE);
3372
                ctx->nip = tmp;
3373
            }
3374
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3375
                gen_debug_exception(ctx);
3376
            }
3377
        }
3378
        tcg_gen_exit_tb(0);
3379
    }
3380
}
3381

    
3382
static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
3383
{
3384
#if defined(TARGET_PPC64)
3385
    if (ctx->sf_mode == 0)
3386
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3387
    else
3388
#endif
3389
        tcg_gen_movi_tl(cpu_lr, nip);
3390
}
3391

    
3392
/* b ba bl bla */
3393
static void gen_b(DisasContext *ctx)
3394
{
3395
    target_ulong li, target;
3396

    
3397
    ctx->exception = POWERPC_EXCP_BRANCH;
3398
    /* sign extend LI */
3399
#if defined(TARGET_PPC64)
3400
    if (ctx->sf_mode)
3401
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3402
    else
3403
#endif
3404
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3405
    if (likely(AA(ctx->opcode) == 0))
3406
        target = ctx->nip + li - 4;
3407
    else
3408
        target = li;
3409
    if (LK(ctx->opcode))
3410
        gen_setlr(ctx, ctx->nip);
3411
    gen_goto_tb(ctx, 0, target);
3412
}
3413

    
3414
#define BCOND_IM  0
3415
#define BCOND_LR  1
3416
#define BCOND_CTR 2
3417

    
3418
static inline void gen_bcond(DisasContext *ctx, int type)
3419
{
3420
    uint32_t bo = BO(ctx->opcode);
3421
    int l1;
3422
    TCGv target;
3423

    
3424
    ctx->exception = POWERPC_EXCP_BRANCH;
3425
    if (type == BCOND_LR || type == BCOND_CTR) {
3426
        target = tcg_temp_local_new();
3427
        if (type == BCOND_CTR)
3428
            tcg_gen_mov_tl(target, cpu_ctr);
3429
        else
3430
            tcg_gen_mov_tl(target, cpu_lr);
3431
    } else {
3432
        TCGV_UNUSED(target);
3433
    }
3434
    if (LK(ctx->opcode))
3435
        gen_setlr(ctx, ctx->nip);
3436
    l1 = gen_new_label();
3437
    if ((bo & 0x4) == 0) {
3438
        /* Decrement and test CTR */
3439
        TCGv temp = tcg_temp_new();
3440
        if (unlikely(type == BCOND_CTR)) {
3441
            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3442
            return;
3443
        }
3444
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3445
#if defined(TARGET_PPC64)
3446
        if (!ctx->sf_mode)
3447
            tcg_gen_ext32u_tl(temp, cpu_ctr);
3448
        else
3449
#endif
3450
            tcg_gen_mov_tl(temp, cpu_ctr);
3451
        if (bo & 0x2) {
3452
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3453
        } else {
3454
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3455
        }
3456
        tcg_temp_free(temp);
3457
    }
3458
    if ((bo & 0x10) == 0) {
3459
        /* Test CR */
3460
        uint32_t bi = BI(ctx->opcode);
3461
        uint32_t mask = 1 << (3 - (bi & 0x03));
3462
        TCGv_i32 temp = tcg_temp_new_i32();
3463

    
3464
        if (bo & 0x8) {
3465
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3466
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3467
        } else {
3468
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3469
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3470
        }
3471
        tcg_temp_free_i32(temp);
3472
    }
3473
    if (type == BCOND_IM) {
3474
        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3475
        if (likely(AA(ctx->opcode) == 0)) {
3476
            gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3477
        } else {
3478
            gen_goto_tb(ctx, 0, li);
3479
        }
3480
        gen_set_label(l1);
3481
        gen_goto_tb(ctx, 1, ctx->nip);
3482
    } else {
3483
#if defined(TARGET_PPC64)
3484
        if (!(ctx->sf_mode))
3485
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3486
        else
3487
#endif
3488
            tcg_gen_andi_tl(cpu_nip, target, ~3);
3489
        tcg_gen_exit_tb(0);
3490
        gen_set_label(l1);
3491
#if defined(TARGET_PPC64)
3492
        if (!(ctx->sf_mode))
3493
            tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
3494
        else
3495
#endif
3496
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
3497
        tcg_gen_exit_tb(0);
3498
    }
3499
}
3500

    
3501
static void gen_bc(DisasContext *ctx)
3502
{
3503
    gen_bcond(ctx, BCOND_IM);
3504
}
3505

    
3506
static void gen_bcctr(DisasContext *ctx)
3507
{
3508
    gen_bcond(ctx, BCOND_CTR);
3509
}
3510

    
3511
static void gen_bclr(DisasContext *ctx)
3512
{
3513
    gen_bcond(ctx, BCOND_LR);
3514
}
3515

    
3516
/***                      Condition register logical                       ***/
3517
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
3518
static void glue(gen_, name)(DisasContext *ctx)                                       \
3519
{                                                                             \
3520
    uint8_t bitmask;                                                          \
3521
    int sh;                                                                   \
3522
    TCGv_i32 t0, t1;                                                          \
3523
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
3524
    t0 = tcg_temp_new_i32();                                                  \
3525
    if (sh > 0)                                                               \
3526
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3527
    else if (sh < 0)                                                          \
3528
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3529
    else                                                                      \
3530
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
3531
    t1 = tcg_temp_new_i32();                                                  \
3532
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
3533
    if (sh > 0)                                                               \
3534
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3535
    else if (sh < 0)                                                          \
3536
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3537
    else                                                                      \
3538
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
3539
    tcg_op(t0, t0, t1);                                                       \
3540
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3541
    tcg_gen_andi_i32(t0, t0, bitmask);                                        \
3542
    tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask);          \
3543
    tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1);                  \
3544
    tcg_temp_free_i32(t0);                                                    \
3545
    tcg_temp_free_i32(t1);                                                    \
3546
}
3547

    
3548
/* crand */
3549
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
3550
/* crandc */
3551
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
3552
/* creqv */
3553
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
3554
/* crnand */
3555
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
3556
/* crnor */
3557
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
3558
/* cror */
3559
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
3560
/* crorc */
3561
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
3562
/* crxor */
3563
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
3564

    
3565
/* mcrf */
3566
static void gen_mcrf(DisasContext *ctx)
3567
{
3568
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
3569
}
3570

    
3571
/***                           System linkage                              ***/
3572

    
3573
/* rfi (mem_idx only) */
3574
static void gen_rfi(DisasContext *ctx)
3575
{
3576
#if defined(CONFIG_USER_ONLY)
3577
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3578
#else
3579
    /* Restore CPU state */
3580
    if (unlikely(!ctx->mem_idx)) {
3581
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3582
        return;
3583
    }
3584
    gen_helper_rfi();
3585
    gen_sync_exception(ctx);
3586
#endif
3587
}
3588

    
3589
#if defined(TARGET_PPC64)
3590
static void gen_rfid(DisasContext *ctx)
3591
{
3592
#if defined(CONFIG_USER_ONLY)
3593
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3594
#else
3595
    /* Restore CPU state */
3596
    if (unlikely(!ctx->mem_idx)) {
3597
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3598
        return;
3599
    }
3600
    gen_helper_rfid();
3601
    gen_sync_exception(ctx);
3602
#endif
3603
}
3604

    
3605
static void gen_hrfid(DisasContext *ctx)
3606
{
3607
#if defined(CONFIG_USER_ONLY)
3608
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3609
#else
3610
    /* Restore CPU state */
3611
    if (unlikely(ctx->mem_idx <= 1)) {
3612
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3613
        return;
3614
    }
3615
    gen_helper_hrfid();
3616
    gen_sync_exception(ctx);
3617
#endif
3618
}
3619
#endif
3620

    
3621
/* sc */
3622
#if defined(CONFIG_USER_ONLY)
3623
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3624
#else
3625
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3626
#endif
3627
static void gen_sc(DisasContext *ctx)
3628
{
3629
    uint32_t lev;
3630

    
3631
    lev = (ctx->opcode >> 5) & 0x7F;
3632
    gen_exception_err(ctx, POWERPC_SYSCALL, lev);
3633
}
3634

    
3635
/***                                Trap                                   ***/
3636

    
3637
/* tw */
3638
static void gen_tw(DisasContext *ctx)
3639
{
3640
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3641
    /* Update the nip since this might generate a trap exception */
3642
    gen_update_nip(ctx, ctx->nip);
3643
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3644
    tcg_temp_free_i32(t0);
3645
}
3646

    
3647
/* twi */
3648
static void gen_twi(DisasContext *ctx)
3649
{
3650
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3651
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3652
    /* Update the nip since this might generate a trap exception */
3653
    gen_update_nip(ctx, ctx->nip);
3654
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
3655
    tcg_temp_free(t0);
3656
    tcg_temp_free_i32(t1);
3657
}
3658

    
3659
#if defined(TARGET_PPC64)
3660
/* td */
3661
static void gen_td(DisasContext *ctx)
3662
{
3663
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3664
    /* Update the nip since this might generate a trap exception */
3665
    gen_update_nip(ctx, ctx->nip);
3666
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3667
    tcg_temp_free_i32(t0);
3668
}
3669

    
3670
/* tdi */
3671
static void gen_tdi(DisasContext *ctx)
3672
{
3673
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3674
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3675
    /* Update the nip since this might generate a trap exception */
3676
    gen_update_nip(ctx, ctx->nip);
3677
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
3678
    tcg_temp_free(t0);
3679
    tcg_temp_free_i32(t1);
3680
}
3681
#endif
3682

    
3683
/***                          Processor control                            ***/
3684

    
3685
/* mcrxr */
3686
static void gen_mcrxr(DisasContext *ctx)
3687
{
3688
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
3689
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3690
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
3691
}
3692

    
3693
/* mfcr mfocrf */
3694
static void gen_mfcr(DisasContext *ctx)
3695
{
3696
    uint32_t crm, crn;
3697

    
3698
    if (likely(ctx->opcode & 0x00100000)) {
3699
        crm = CRM(ctx->opcode);
3700
        if (likely(crm && ((crm & (crm - 1)) == 0))) {
3701
            crn = ctz32 (crm);
3702
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
3703
            tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
3704
                            cpu_gpr[rD(ctx->opcode)], crn * 4);
3705
        }
3706
    } else {
3707
        TCGv_i32 t0 = tcg_temp_new_i32();
3708
        tcg_gen_mov_i32(t0, cpu_crf[0]);
3709
        tcg_gen_shli_i32(t0, t0, 4);
3710
        tcg_gen_or_i32(t0, t0, cpu_crf[1]);
3711
        tcg_gen_shli_i32(t0, t0, 4);
3712
        tcg_gen_or_i32(t0, t0, cpu_crf[2]);
3713
        tcg_gen_shli_i32(t0, t0, 4);
3714
        tcg_gen_or_i32(t0, t0, cpu_crf[3]);
3715
        tcg_gen_shli_i32(t0, t0, 4);
3716
        tcg_gen_or_i32(t0, t0, cpu_crf[4]);
3717
        tcg_gen_shli_i32(t0, t0, 4);
3718
        tcg_gen_or_i32(t0, t0, cpu_crf[5]);
3719
        tcg_gen_shli_i32(t0, t0, 4);
3720
        tcg_gen_or_i32(t0, t0, cpu_crf[6]);
3721
        tcg_gen_shli_i32(t0, t0, 4);
3722
        tcg_gen_or_i32(t0, t0, cpu_crf[7]);
3723
        tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
3724
        tcg_temp_free_i32(t0);
3725
    }
3726
}
3727

    
3728
/* mfmsr */
3729
static void gen_mfmsr(DisasContext *ctx)
3730
{
3731
#if defined(CONFIG_USER_ONLY)
3732
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3733
#else
3734
    if (unlikely(!ctx->mem_idx)) {
3735
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3736
        return;
3737
    }
3738
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3739
#endif
3740
}
3741

    
3742
static void spr_noaccess(void *opaque, int gprn, int sprn)
3743
{
3744
#if 0
3745
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3746
    printf("ERROR: try to access SPR %d !\n", sprn);
3747
#endif
3748
}
3749
#define SPR_NOACCESS (&spr_noaccess)
3750

    
3751
/* mfspr */
3752
static inline void gen_op_mfspr(DisasContext *ctx)
3753
{
3754
    void (*read_cb)(void *opaque, int gprn, int sprn);
3755
    uint32_t sprn = SPR(ctx->opcode);
3756

    
3757
#if !defined(CONFIG_USER_ONLY)
3758
    if (ctx->mem_idx == 2)
3759
        read_cb = ctx->spr_cb[sprn].hea_read;
3760
    else if (ctx->mem_idx)
3761
        read_cb = ctx->spr_cb[sprn].oea_read;
3762
    else
3763
#endif
3764
        read_cb = ctx->spr_cb[sprn].uea_read;
3765
    if (likely(read_cb != NULL)) {
3766
        if (likely(read_cb != SPR_NOACCESS)) {
3767
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3768
        } else {
3769
            /* Privilege exception */
3770
            /* This is a hack to avoid warnings when running Linux:
3771
             * this OS breaks the PowerPC virtualisation model,
3772
             * allowing userland application to read the PVR
3773
             */
3774
            if (sprn != SPR_PVR) {
3775
                qemu_log("Trying to read privileged spr %d %03x at "
3776
                         TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3777
                printf("Trying to read privileged spr %d %03x at "
3778
                       TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3779
            }
3780
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3781
        }
3782
    } else {
3783
        /* Not defined */
3784
        qemu_log("Trying to read invalid spr %d %03x at "
3785
                    TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3786
        printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
3787
               sprn, sprn, ctx->nip);
3788
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
3789
    }
3790
}
3791

    
3792
static void gen_mfspr(DisasContext *ctx)
3793
{
3794
    gen_op_mfspr(ctx);
3795
}
3796

    
3797
/* mftb */
3798
static void gen_mftb(DisasContext *ctx)
3799
{
3800
    gen_op_mfspr(ctx);
3801
}
3802

    
3803
/* mtcrf mtocrf*/
3804
static void gen_mtcrf(DisasContext *ctx)
3805
{
3806
    uint32_t crm, crn;
3807

    
3808
    crm = CRM(ctx->opcode);
3809
    if (likely((ctx->opcode & 0x00100000))) {
3810
        if (crm && ((crm & (crm - 1)) == 0)) {
3811
            TCGv_i32 temp = tcg_temp_new_i32();
3812
            crn = ctz32 (crm);
3813
            tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3814
            tcg_gen_shri_i32(temp, temp, crn * 4);
3815
            tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
3816
            tcg_temp_free_i32(temp);
3817
        }
3818
    } else {
3819
        TCGv_i32 temp = tcg_temp_new_i32();
3820
        tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3821
        for (crn = 0 ; crn < 8 ; crn++) {
3822
            if (crm & (1 << crn)) {
3823
                    tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
3824
                    tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3825
            }
3826
        }
3827
        tcg_temp_free_i32(temp);
3828
    }
3829
}
3830

    
3831
/* mtmsr */
3832
#if defined(TARGET_PPC64)
3833
static void gen_mtmsrd(DisasContext *ctx)
3834
{
3835
#if defined(CONFIG_USER_ONLY)
3836
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3837
#else
3838
    if (unlikely(!ctx->mem_idx)) {
3839
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3840
        return;
3841
    }
3842
    if (ctx->opcode & 0x00010000) {
3843
        /* Special form that does not need any synchronisation */
3844
        TCGv t0 = tcg_temp_new();
3845
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3846
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3847
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3848
        tcg_temp_free(t0);
3849
    } else {
3850
        /* XXX: we need to update nip before the store
3851
         *      if we enter power saving mode, we will exit the loop
3852
         *      directly from ppc_store_msr
3853
         */
3854
        gen_update_nip(ctx, ctx->nip);
3855
        gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3856
        /* Must stop the translation as machine state (may have) changed */
3857
        /* Note that mtmsr is not always defined as context-synchronizing */
3858
        gen_stop_exception(ctx);
3859
    }
3860
#endif
3861
}
3862
#endif
3863

    
3864
static void gen_mtmsr(DisasContext *ctx)
3865
{
3866
#if defined(CONFIG_USER_ONLY)
3867
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3868
#else
3869
    if (unlikely(!ctx->mem_idx)) {
3870
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3871
        return;
3872
    }
3873
    if (ctx->opcode & 0x00010000) {
3874
        /* Special form that does not need any synchronisation */
3875
        TCGv t0 = tcg_temp_new();
3876
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3877
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3878
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3879
        tcg_temp_free(t0);
3880
    } else {
3881
        /* XXX: we need to update nip before the store
3882
         *      if we enter power saving mode, we will exit the loop
3883
         *      directly from ppc_store_msr
3884
         */
3885
        gen_update_nip(ctx, ctx->nip);
3886
#if defined(TARGET_PPC64)
3887
        if (!ctx->sf_mode) {
3888
            TCGv t0 = tcg_temp_new();
3889
            TCGv t1 = tcg_temp_new();
3890
            tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
3891
            tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
3892
            tcg_gen_or_tl(t0, t0, t1);
3893
            tcg_temp_free(t1);
3894
            gen_helper_store_msr(t0);
3895
            tcg_temp_free(t0);
3896
        } else
3897
#endif
3898
            gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3899
        /* Must stop the translation as machine state (may have) changed */
3900
        /* Note that mtmsr is not always defined as context-synchronizing */
3901
        gen_stop_exception(ctx);
3902
    }
3903
#endif
3904
}
3905

    
3906
/* mtspr */
3907
static void gen_mtspr(DisasContext *ctx)
3908
{
3909
    void (*write_cb)(void *opaque, int sprn, int gprn);
3910
    uint32_t sprn = SPR(ctx->opcode);
3911

    
3912
#if !defined(CONFIG_USER_ONLY)
3913
    if (ctx->mem_idx == 2)
3914
        write_cb = ctx->spr_cb[sprn].hea_write;
3915
    else if (ctx->mem_idx)
3916
        write_cb = ctx->spr_cb[sprn].oea_write;
3917
    else
3918
#endif
3919
        write_cb = ctx->spr_cb[sprn].uea_write;
3920
    if (likely(write_cb != NULL)) {
3921
        if (likely(write_cb != SPR_NOACCESS)) {
3922
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
3923
        } else {
3924
            /* Privilege exception */
3925
            qemu_log("Trying to write privileged spr %d %03x at "
3926
                     TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3927
            printf("Trying to write privileged spr %d %03x at " TARGET_FMT_lx
3928
                   "\n", sprn, sprn, ctx->nip);
3929
            gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
3930
        }
3931
    } else {
3932
        /* Not defined */
3933
        qemu_log("Trying to write invalid spr %d %03x at "
3934
                 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3935
        printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
3936
               sprn, sprn, ctx->nip);
3937
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
3938
    }
3939
}
3940

    
3941
/***                         Cache management                              ***/
3942

    
3943
/* dcbf */
3944
static void gen_dcbf(DisasContext *ctx)
3945
{
3946
    /* XXX: specification says this is treated as a load by the MMU */
3947
    TCGv t0;
3948
    gen_set_access_type(ctx, ACCESS_CACHE);
3949
    t0 = tcg_temp_new();
3950
    gen_addr_reg_index(ctx, t0);
3951
    gen_qemu_ld8u(ctx, t0, t0);
3952
    tcg_temp_free(t0);
3953
}
3954

    
3955
/* dcbi (Supervisor only) */
3956
static void gen_dcbi(DisasContext *ctx)
3957
{
3958
#if defined(CONFIG_USER_ONLY)
3959
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3960
#else
3961
    TCGv EA, val;
3962
    if (unlikely(!ctx->mem_idx)) {
3963
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
3964
        return;
3965
    }
3966
    EA = tcg_temp_new();
3967
    gen_set_access_type(ctx, ACCESS_CACHE);
3968
    gen_addr_reg_index(ctx, EA);
3969
    val = tcg_temp_new();
3970
    /* XXX: specification says this should be treated as a store by the MMU */
3971
    gen_qemu_ld8u(ctx, val, EA);
3972
    gen_qemu_st8(ctx, val, EA);
3973
    tcg_temp_free(val);
3974
    tcg_temp_free(EA);
3975
#endif
3976
}
3977

    
3978
/* dcdst */
3979
static void gen_dcbst(DisasContext *ctx)
3980
{
3981
    /* XXX: specification say this is treated as a load by the MMU */
3982
    TCGv t0;
3983
    gen_set_access_type(ctx, ACCESS_CACHE);
3984
    t0 = tcg_temp_new();
3985
    gen_addr_reg_index(ctx, t0);
3986
    gen_qemu_ld8u(ctx, t0, t0);
3987
    tcg_temp_free(t0);
3988
}
3989

    
3990
/* dcbt */
3991
static void gen_dcbt(DisasContext *ctx)
3992
{
3993
    /* interpreted as no-op */
3994
    /* XXX: specification say this is treated as a load by the MMU
3995
     *      but does not generate any exception
3996
     */
3997
}
3998

    
3999
/* dcbtst */
4000
static void gen_dcbtst(DisasContext *ctx)
4001
{
4002
    /* interpreted as no-op */
4003
    /* XXX: specification say this is treated as a load by the MMU
4004
     *      but does not generate any exception
4005
     */
4006
}
4007

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

    
4021
static void gen_dcbz_970(DisasContext *ctx)
4022
{
4023
    TCGv t0;
4024
    gen_set_access_type(ctx, ACCESS_CACHE);
4025
    /* NIP cannot be restored if the memory exception comes from an helper */
4026
    gen_update_nip(ctx, ctx->nip - 4);
4027
    t0 = tcg_temp_new();
4028
    gen_addr_reg_index(ctx, t0);
4029
    if (ctx->opcode & 0x00200000)
4030
        gen_helper_dcbz(t0);
4031
    else
4032
        gen_helper_dcbz_970(t0);
4033
    tcg_temp_free(t0);
4034
}
4035

    
4036
/* dst / dstt */
4037
static void gen_dst(DisasContext *ctx)
4038
{
4039
    if (rA(ctx->opcode) == 0) {
4040
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4041
    } else {
4042
        /* interpreted as no-op */
4043
    }
4044
}
4045

    
4046
/* dstst /dststt */
4047
static void gen_dstst(DisasContext *ctx)
4048
{
4049
    if (rA(ctx->opcode) == 0) {
4050
        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4051
    } else {
4052
        /* interpreted as no-op */
4053
    }
4054

    
4055
}
4056

    
4057
/* dss / dssall */
4058
static void gen_dss(DisasContext *ctx)
4059
{
4060
    /* interpreted as no-op */
4061
}
4062

    
4063
/* icbi */
4064
static void gen_icbi(DisasContext *ctx)
4065
{
4066
    TCGv t0;
4067
    gen_set_access_type(ctx, ACCESS_CACHE);
4068
    /* NIP cannot be restored if the memory exception comes from an helper */
4069
    gen_update_nip(ctx, ctx->nip - 4);
4070
    t0 = tcg_temp_new();
4071
    gen_addr_reg_index(ctx, t0);
4072
    gen_helper_icbi(t0);
4073
    tcg_temp_free(t0);
4074
}
4075

    
4076
/* Optional: */
4077
/* dcba */
4078
static void gen_dcba(DisasContext *ctx)
4079
{
4080
    /* interpreted as no-op */
4081
    /* XXX: specification say this is treated as a store by the MMU
4082
     *      but does not generate any exception
4083
     */
4084
}
4085

    
4086
/***                    Segment register manipulation                      ***/
4087
/* Supervisor only: */
4088

    
4089
/* mfsr */
4090
static void gen_mfsr(DisasContext *ctx)
4091
{
4092
#if defined(CONFIG_USER_ONLY)
4093
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4094
#else
4095
    TCGv t0;
4096
    if (unlikely(!ctx->mem_idx)) {
4097
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4098
        return;
4099
    }
4100
    t0 = tcg_const_tl(SR(ctx->opcode));
4101
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4102
    tcg_temp_free(t0);
4103
#endif
4104
}
4105

    
4106
/* mfsrin */
4107
static void gen_mfsrin(DisasContext *ctx)
4108
{
4109
#if defined(CONFIG_USER_ONLY)
4110
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4111
#else
4112
    TCGv t0;
4113
    if (unlikely(!ctx->mem_idx)) {
4114
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4115
        return;
4116
    }
4117
    t0 = tcg_temp_new();
4118
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4119
    tcg_gen_andi_tl(t0, t0, 0xF);
4120
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4121
    tcg_temp_free(t0);
4122
#endif
4123
}
4124

    
4125
/* mtsr */
4126
static void gen_mtsr(DisasContext *ctx)
4127
{
4128
#if defined(CONFIG_USER_ONLY)
4129
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4130
#else
4131
    TCGv t0;
4132
    if (unlikely(!ctx->mem_idx)) {
4133
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4134
        return;
4135
    }
4136
    t0 = tcg_const_tl(SR(ctx->opcode));
4137
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4138
    tcg_temp_free(t0);
4139
#endif
4140
}
4141

    
4142
/* mtsrin */
4143
static void gen_mtsrin(DisasContext *ctx)
4144
{
4145
#if defined(CONFIG_USER_ONLY)
4146
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4147
#else
4148
    TCGv t0;
4149
    if (unlikely(!ctx->mem_idx)) {
4150
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4151
        return;
4152
    }
4153
    t0 = tcg_temp_new();
4154
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4155
    tcg_gen_andi_tl(t0, t0, 0xF);
4156
    gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
4157
    tcg_temp_free(t0);
4158
#endif
4159
}
4160

    
4161
#if defined(TARGET_PPC64)
4162
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
4163

    
4164
/* mfsr */
4165
static void gen_mfsr_64b(DisasContext *ctx)
4166
{
4167
#if defined(CONFIG_USER_ONLY)
4168
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4169
#else
4170
    TCGv t0;
4171
    if (unlikely(!ctx->mem_idx)) {
4172
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4173
        return;
4174
    }
4175
    t0 = tcg_const_tl(SR(ctx->opcode));
4176
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4177
    tcg_temp_free(t0);
4178
#endif
4179
}
4180

    
4181
/* mfsrin */
4182
static void gen_mfsrin_64b(DisasContext *ctx)
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_temp_new();
4193
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4194
    tcg_gen_andi_tl(t0, t0, 0xF);
4195
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4196
    tcg_temp_free(t0);
4197
#endif
4198
}
4199

    
4200
/* mtsr */
4201
static void gen_mtsr_64b(DisasContext *ctx)
4202
{
4203
#if defined(CONFIG_USER_ONLY)
4204
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4205
#else
4206
    TCGv t0;
4207
    if (unlikely(!ctx->mem_idx)) {
4208
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4209
        return;
4210
    }
4211
    t0 = tcg_const_tl(SR(ctx->opcode));
4212
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4213
    tcg_temp_free(t0);
4214
#endif
4215
}
4216

    
4217
/* mtsrin */
4218
static void gen_mtsrin_64b(DisasContext *ctx)
4219
{
4220
#if defined(CONFIG_USER_ONLY)
4221
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4222
#else
4223
    TCGv t0;
4224
    if (unlikely(!ctx->mem_idx)) {
4225
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4226
        return;
4227
    }
4228
    t0 = tcg_temp_new();
4229
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4230
    tcg_gen_andi_tl(t0, t0, 0xF);
4231
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4232
    tcg_temp_free(t0);
4233
#endif
4234
}
4235

    
4236
/* slbmte */
4237
static void gen_slbmte(DisasContext *ctx)
4238
{
4239
#if defined(CONFIG_USER_ONLY)
4240
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4241
#else
4242
    if (unlikely(!ctx->mem_idx)) {
4243
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4244
        return;
4245
    }
4246
    gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
4247
#endif
4248
}
4249

    
4250
static void gen_slbmfee(DisasContext *ctx)
4251
{
4252
#if defined(CONFIG_USER_ONLY)
4253
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4254
#else
4255
    if (unlikely(!ctx->mem_idx)) {
4256
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4257
        return;
4258
    }
4259
    gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)],
4260
                             cpu_gpr[rB(ctx->opcode)]);
4261
#endif
4262
}
4263

    
4264
static void gen_slbmfev(DisasContext *ctx)
4265
{
4266
#if defined(CONFIG_USER_ONLY)
4267
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4268
#else
4269
    if (unlikely(!ctx->mem_idx)) {
4270
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4271
        return;
4272
    }
4273
    gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)],
4274
                             cpu_gpr[rB(ctx->opcode)]);
4275
#endif
4276
}
4277
#endif /* defined(TARGET_PPC64) */
4278

    
4279
/***                      Lookaside buffer management                      ***/
4280
/* Optional & mem_idx only: */
4281

    
4282
/* tlbia */
4283
static void gen_tlbia(DisasContext *ctx)
4284
{
4285
#if defined(CONFIG_USER_ONLY)
4286
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4287
#else
4288
    if (unlikely(!ctx->mem_idx)) {
4289
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4290
        return;
4291
    }
4292
    gen_helper_tlbia();
4293
#endif
4294
}
4295

    
4296
/* tlbiel */
4297
static void gen_tlbiel(DisasContext *ctx)
4298
{
4299
#if defined(CONFIG_USER_ONLY)
4300
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4301
#else
4302
    if (unlikely(!ctx->mem_idx)) {
4303
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4304
        return;
4305
    }
4306
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4307
#endif
4308
}
4309

    
4310
/* tlbie */
4311
static void gen_tlbie(DisasContext *ctx)
4312
{
4313
#if defined(CONFIG_USER_ONLY)
4314
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4315
#else
4316
    if (unlikely(!ctx->mem_idx)) {
4317
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4318
        return;
4319
    }
4320
#if defined(TARGET_PPC64)
4321
    if (!ctx->sf_mode) {
4322
        TCGv t0 = tcg_temp_new();
4323
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4324
        gen_helper_tlbie(t0);
4325
        tcg_temp_free(t0);
4326
    } else
4327
#endif
4328
        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4329
#endif
4330
}
4331

    
4332
/* tlbsync */
4333
static void gen_tlbsync(DisasContext *ctx)
4334
{
4335
#if defined(CONFIG_USER_ONLY)
4336
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4337
#else
4338
    if (unlikely(!ctx->mem_idx)) {
4339
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4340
        return;
4341
    }
4342
    /* This has no effect: it should ensure that all previous
4343
     * tlbie have completed
4344
     */
4345
    gen_stop_exception(ctx);
4346
#endif
4347
}
4348

    
4349
#if defined(TARGET_PPC64)
4350
/* slbia */
4351
static void gen_slbia(DisasContext *ctx)
4352
{
4353
#if defined(CONFIG_USER_ONLY)
4354
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4355
#else
4356
    if (unlikely(!ctx->mem_idx)) {
4357
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4358
        return;
4359
    }
4360
    gen_helper_slbia();
4361
#endif
4362
}
4363

    
4364
/* slbie */
4365
static void gen_slbie(DisasContext *ctx)
4366
{
4367
#if defined(CONFIG_USER_ONLY)
4368
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4369
#else
4370
    if (unlikely(!ctx->mem_idx)) {
4371
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4372
        return;
4373
    }
4374
    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
4375
#endif
4376
}
4377
#endif
4378

    
4379
/***                              External control                         ***/
4380
/* Optional: */
4381

    
4382
/* eciwx */
4383
static void gen_eciwx(DisasContext *ctx)
4384
{
4385
    TCGv t0;
4386
    /* Should check EAR[E] ! */
4387
    gen_set_access_type(ctx, ACCESS_EXT);
4388
    t0 = tcg_temp_new();
4389
    gen_addr_reg_index(ctx, t0);
4390
    gen_check_align(ctx, t0, 0x03);
4391
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4392
    tcg_temp_free(t0);
4393
}
4394

    
4395
/* ecowx */
4396
static void gen_ecowx(DisasContext *ctx)
4397
{
4398
    TCGv t0;
4399
    /* Should check EAR[E] ! */
4400
    gen_set_access_type(ctx, ACCESS_EXT);
4401
    t0 = tcg_temp_new();
4402
    gen_addr_reg_index(ctx, t0);
4403
    gen_check_align(ctx, t0, 0x03);
4404
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4405
    tcg_temp_free(t0);
4406
}
4407

    
4408
/* PowerPC 601 specific instructions */
4409

    
4410
/* abs - abs. */
4411
static void gen_abs(DisasContext *ctx)
4412
{
4413
    int l1 = gen_new_label();
4414
    int l2 = gen_new_label();
4415
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4416
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4417
    tcg_gen_br(l2);
4418
    gen_set_label(l1);
4419
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4420
    gen_set_label(l2);
4421
    if (unlikely(Rc(ctx->opcode) != 0))
4422
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4423
}
4424

    
4425
/* abso - abso. */
4426
static void gen_abso(DisasContext *ctx)
4427
{
4428
    int l1 = gen_new_label();
4429
    int l2 = gen_new_label();
4430
    int l3 = gen_new_label();
4431
    /* Start with XER OV disabled, the most likely case */
4432
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4433
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4434
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4435
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4436
    tcg_gen_br(l2);
4437
    gen_set_label(l1);
4438
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4439
    tcg_gen_br(l3);
4440
    gen_set_label(l2);
4441
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4442
    gen_set_label(l3);
4443
    if (unlikely(Rc(ctx->opcode) != 0))
4444
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4445
}
4446

    
4447
/* clcs */
4448
static void gen_clcs(DisasContext *ctx)
4449
{
4450
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4451
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
4452
    tcg_temp_free_i32(t0);
4453
    /* Rc=1 sets CR0 to an undefined state */
4454
}
4455

    
4456
/* div - div. */
4457
static void gen_div(DisasContext *ctx)
4458
{
4459
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4460
    if (unlikely(Rc(ctx->opcode) != 0))
4461
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4462
}
4463

    
4464
/* divo - divo. */
4465
static void gen_divo(DisasContext *ctx)
4466
{
4467
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4468
    if (unlikely(Rc(ctx->opcode) != 0))
4469
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4470
}
4471

    
4472
/* divs - divs. */
4473
static void gen_divs(DisasContext *ctx)
4474
{
4475
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4476
    if (unlikely(Rc(ctx->opcode) != 0))
4477
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4478
}
4479

    
4480
/* divso - divso. */
4481
static void gen_divso(DisasContext *ctx)
4482
{
4483
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4484
    if (unlikely(Rc(ctx->opcode) != 0))
4485
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4486
}
4487

    
4488
/* doz - doz. */
4489
static void gen_doz(DisasContext *ctx)
4490
{
4491
    int l1 = gen_new_label();
4492
    int l2 = gen_new_label();
4493
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4494
    tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4495
    tcg_gen_br(l2);
4496
    gen_set_label(l1);
4497
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4498
    gen_set_label(l2);
4499
    if (unlikely(Rc(ctx->opcode) != 0))
4500
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4501
}
4502

    
4503
/* dozo - dozo. */
4504
static void gen_dozo(DisasContext *ctx)
4505
{
4506
    int l1 = gen_new_label();
4507
    int l2 = gen_new_label();
4508
    TCGv t0 = tcg_temp_new();
4509
    TCGv t1 = tcg_temp_new();
4510
    TCGv t2 = tcg_temp_new();
4511
    /* Start with XER OV disabled, the most likely case */
4512
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4513
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4514
    tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4515
    tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4516
    tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4517
    tcg_gen_andc_tl(t1, t1, t2);
4518
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4519
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4520
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4521
    tcg_gen_br(l2);
4522
    gen_set_label(l1);
4523
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4524
    gen_set_label(l2);
4525
    tcg_temp_free(t0);
4526
    tcg_temp_free(t1);
4527
    tcg_temp_free(t2);
4528
    if (unlikely(Rc(ctx->opcode) != 0))
4529
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4530
}
4531

    
4532
/* dozi */
4533
static void gen_dozi(DisasContext *ctx)
4534
{
4535
    target_long simm = SIMM(ctx->opcode);
4536
    int l1 = gen_new_label();
4537
    int l2 = gen_new_label();
4538
    tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4539
    tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4540
    tcg_gen_br(l2);
4541
    gen_set_label(l1);
4542
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4543
    gen_set_label(l2);
4544
    if (unlikely(Rc(ctx->opcode) != 0))
4545
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4546
}
4547

    
4548
/* lscbx - lscbx. */
4549
static void gen_lscbx(DisasContext *ctx)
4550
{
4551
    TCGv t0 = tcg_temp_new();
4552
    TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4553
    TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4554
    TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
4555

    
4556
    gen_addr_reg_index(ctx, t0);
4557
    /* NIP cannot be restored if the memory exception comes from an helper */
4558
    gen_update_nip(ctx, ctx->nip - 4);
4559
    gen_helper_lscbx(t0, t0, t1, t2, t3);
4560
    tcg_temp_free_i32(t1);
4561
    tcg_temp_free_i32(t2);
4562
    tcg_temp_free_i32(t3);
4563
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4564
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4565
    if (unlikely(Rc(ctx->opcode) != 0))
4566
        gen_set_Rc0(ctx, t0);
4567
    tcg_temp_free(t0);
4568
}
4569

    
4570
/* maskg - maskg. */
4571
static void gen_maskg(DisasContext *ctx)
4572
{
4573
    int l1 = gen_new_label();
4574
    TCGv t0 = tcg_temp_new();
4575
    TCGv t1 = tcg_temp_new();
4576
    TCGv t2 = tcg_temp_new();
4577
    TCGv t3 = tcg_temp_new();
4578
    tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4579
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4580
    tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4581
    tcg_gen_addi_tl(t2, t0, 1);
4582
    tcg_gen_shr_tl(t2, t3, t2);
4583
    tcg_gen_shr_tl(t3, t3, t1);
4584
    tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4585
    tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4586
    tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4587
    gen_set_label(l1);
4588
    tcg_temp_free(t0);
4589
    tcg_temp_free(t1);
4590
    tcg_temp_free(t2);
4591
    tcg_temp_free(t3);
4592
    if (unlikely(Rc(ctx->opcode) != 0))
4593
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4594
}
4595

    
4596
/* maskir - maskir. */
4597
static void gen_maskir(DisasContext *ctx)
4598
{
4599
    TCGv t0 = tcg_temp_new();
4600
    TCGv t1 = tcg_temp_new();
4601
    tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4602
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4603
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4604
    tcg_temp_free(t0);
4605
    tcg_temp_free(t1);
4606
    if (unlikely(Rc(ctx->opcode) != 0))
4607
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4608
}
4609

    
4610
/* mul - mul. */
4611
static void gen_mul(DisasContext *ctx)
4612
{
4613
    TCGv_i64 t0 = tcg_temp_new_i64();
4614
    TCGv_i64 t1 = tcg_temp_new_i64();
4615
    TCGv t2 = tcg_temp_new();
4616
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4617
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4618
    tcg_gen_mul_i64(t0, t0, t1);
4619
    tcg_gen_trunc_i64_tl(t2, t0);
4620
    gen_store_spr(SPR_MQ, t2);
4621
    tcg_gen_shri_i64(t1, t0, 32);
4622
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4623
    tcg_temp_free_i64(t0);
4624
    tcg_temp_free_i64(t1);
4625
    tcg_temp_free(t2);
4626
    if (unlikely(Rc(ctx->opcode) != 0))
4627
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4628
}
4629

    
4630
/* mulo - mulo. */
4631
static void gen_mulo(DisasContext *ctx)
4632
{
4633
    int l1 = gen_new_label();
4634
    TCGv_i64 t0 = tcg_temp_new_i64();
4635
    TCGv_i64 t1 = tcg_temp_new_i64();
4636
    TCGv t2 = tcg_temp_new();
4637
    /* Start with XER OV disabled, the most likely case */
4638
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4639
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4640
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4641
    tcg_gen_mul_i64(t0, t0, t1);
4642
    tcg_gen_trunc_i64_tl(t2, t0);
4643
    gen_store_spr(SPR_MQ, t2);
4644
    tcg_gen_shri_i64(t1, t0, 32);
4645
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4646
    tcg_gen_ext32s_i64(t1, t0);
4647
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4648
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4649
    gen_set_label(l1);
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
/* nabs - nabs. */
4658
static void gen_nabs(DisasContext *ctx)
4659
{
4660
    int l1 = gen_new_label();
4661
    int l2 = gen_new_label();
4662
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4663
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4664
    tcg_gen_br(l2);
4665
    gen_set_label(l1);
4666
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4667
    gen_set_label(l2);
4668
    if (unlikely(Rc(ctx->opcode) != 0))
4669
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4670
}
4671

    
4672
/* nabso - nabso. */
4673
static void gen_nabso(DisasContext *ctx)
4674
{
4675
    int l1 = gen_new_label();
4676
    int l2 = gen_new_label();
4677
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4678
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4679
    tcg_gen_br(l2);
4680
    gen_set_label(l1);
4681
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4682
    gen_set_label(l2);
4683
    /* nabs never overflows */
4684
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4685
    if (unlikely(Rc(ctx->opcode) != 0))
4686
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4687
}
4688

    
4689
/* rlmi - rlmi. */
4690
static void gen_rlmi(DisasContext *ctx)
4691
{
4692
    uint32_t mb = MB(ctx->opcode);
4693
    uint32_t me = ME(ctx->opcode);
4694
    TCGv t0 = tcg_temp_new();
4695
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4696
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4697
    tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4698
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4699
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4700
    tcg_temp_free(t0);
4701
    if (unlikely(Rc(ctx->opcode) != 0))
4702
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4703
}
4704

    
4705
/* rrib - rrib. */
4706
static void gen_rrib(DisasContext *ctx)
4707
{
4708
    TCGv t0 = tcg_temp_new();
4709
    TCGv t1 = tcg_temp_new();
4710
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4711
    tcg_gen_movi_tl(t1, 0x80000000);
4712
    tcg_gen_shr_tl(t1, t1, t0);
4713
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4714
    tcg_gen_and_tl(t0, t0, t1);
4715
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4716
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4717
    tcg_temp_free(t0);
4718
    tcg_temp_free(t1);
4719
    if (unlikely(Rc(ctx->opcode) != 0))
4720
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4721
}
4722

    
4723
/* sle - sle. */
4724
static void gen_sle(DisasContext *ctx)
4725
{
4726
    TCGv t0 = tcg_temp_new();
4727
    TCGv t1 = tcg_temp_new();
4728
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4729
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4730
    tcg_gen_subfi_tl(t1, 32, t1);
4731
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4732
    tcg_gen_or_tl(t1, t0, t1);
4733
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4734
    gen_store_spr(SPR_MQ, t1);
4735
    tcg_temp_free(t0);
4736
    tcg_temp_free(t1);
4737
    if (unlikely(Rc(ctx->opcode) != 0))
4738
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4739
}
4740

    
4741
/* sleq - sleq. */
4742
static void gen_sleq(DisasContext *ctx)
4743
{
4744
    TCGv t0 = tcg_temp_new();
4745
    TCGv t1 = tcg_temp_new();
4746
    TCGv t2 = tcg_temp_new();
4747
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4748
    tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4749
    tcg_gen_shl_tl(t2, t2, t0);
4750
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4751
    gen_load_spr(t1, SPR_MQ);
4752
    gen_store_spr(SPR_MQ, t0);
4753
    tcg_gen_and_tl(t0, t0, t2);
4754
    tcg_gen_andc_tl(t1, t1, t2);
4755
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4756
    tcg_temp_free(t0);
4757
    tcg_temp_free(t1);
4758
    tcg_temp_free(t2);
4759
    if (unlikely(Rc(ctx->opcode) != 0))
4760
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4761
}
4762

    
4763
/* sliq - sliq. */
4764
static void gen_sliq(DisasContext *ctx)
4765
{
4766
    int sh = SH(ctx->opcode);
4767
    TCGv t0 = tcg_temp_new();
4768
    TCGv t1 = tcg_temp_new();
4769
    tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4770
    tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4771
    tcg_gen_or_tl(t1, t0, t1);
4772
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4773
    gen_store_spr(SPR_MQ, t1);
4774
    tcg_temp_free(t0);
4775
    tcg_temp_free(t1);
4776
    if (unlikely(Rc(ctx->opcode) != 0))
4777
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4778
}
4779

    
4780
/* slliq - slliq. */
4781
static void gen_slliq(DisasContext *ctx)
4782
{
4783
    int sh = SH(ctx->opcode);
4784
    TCGv t0 = tcg_temp_new();
4785
    TCGv t1 = tcg_temp_new();
4786
    tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4787
    gen_load_spr(t1, SPR_MQ);
4788
    gen_store_spr(SPR_MQ, t0);
4789
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU << sh));
4790
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
4791
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4792
    tcg_temp_free(t0);
4793
    tcg_temp_free(t1);
4794
    if (unlikely(Rc(ctx->opcode) != 0))
4795
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4796
}
4797

    
4798
/* sllq - sllq. */
4799
static void gen_sllq(DisasContext *ctx)
4800
{
4801
    int l1 = gen_new_label();
4802
    int l2 = gen_new_label();
4803
    TCGv t0 = tcg_temp_local_new();
4804
    TCGv t1 = tcg_temp_local_new();
4805
    TCGv t2 = tcg_temp_local_new();
4806
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4807
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4808
    tcg_gen_shl_tl(t1, t1, t2);
4809
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4810
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4811
    gen_load_spr(t0, SPR_MQ);
4812
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4813
    tcg_gen_br(l2);
4814
    gen_set_label(l1);
4815
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4816
    gen_load_spr(t2, SPR_MQ);
4817
    tcg_gen_andc_tl(t1, t2, t1);
4818
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4819
    gen_set_label(l2);
4820
    tcg_temp_free(t0);
4821
    tcg_temp_free(t1);
4822
    tcg_temp_free(t2);
4823
    if (unlikely(Rc(ctx->opcode) != 0))
4824
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4825
}
4826

    
4827
/* slq - slq. */
4828
static void gen_slq(DisasContext *ctx)
4829
{
4830
    int l1 = gen_new_label();
4831
    TCGv t0 = tcg_temp_new();
4832
    TCGv t1 = tcg_temp_new();
4833
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4834
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4835
    tcg_gen_subfi_tl(t1, 32, t1);
4836
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4837
    tcg_gen_or_tl(t1, t0, t1);
4838
    gen_store_spr(SPR_MQ, t1);
4839
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4840
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4841
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4842
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4843
    gen_set_label(l1);
4844
    tcg_temp_free(t0);
4845
    tcg_temp_free(t1);
4846
    if (unlikely(Rc(ctx->opcode) != 0))
4847
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4848
}
4849

    
4850
/* sraiq - sraiq. */
4851
static void gen_sraiq(DisasContext *ctx)
4852
{
4853
    int sh = SH(ctx->opcode);
4854
    int l1 = gen_new_label();
4855
    TCGv t0 = tcg_temp_new();
4856
    TCGv t1 = tcg_temp_new();
4857
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4858
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4859
    tcg_gen_or_tl(t0, t0, t1);
4860
    gen_store_spr(SPR_MQ, t0);
4861
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4862
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4863
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4864
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4865
    gen_set_label(l1);
4866
    tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
4867
    tcg_temp_free(t0);
4868
    tcg_temp_free(t1);
4869
    if (unlikely(Rc(ctx->opcode) != 0))
4870
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4871
}
4872

    
4873
/* sraq - sraq. */
4874
static void gen_sraq(DisasContext *ctx)
4875
{
4876
    int l1 = gen_new_label();
4877
    int l2 = gen_new_label();
4878
    TCGv t0 = tcg_temp_new();
4879
    TCGv t1 = tcg_temp_local_new();
4880
    TCGv t2 = tcg_temp_local_new();
4881
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4882
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4883
    tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
4884
    tcg_gen_subfi_tl(t2, 32, t2);
4885
    tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
4886
    tcg_gen_or_tl(t0, t0, t2);
4887
    gen_store_spr(SPR_MQ, t0);
4888
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4889
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
4890
    tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
4891
    tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
4892
    gen_set_label(l1);
4893
    tcg_temp_free(t0);
4894
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4895
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4896
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4897
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4898
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4899
    gen_set_label(l2);
4900
    tcg_temp_free(t1);
4901
    tcg_temp_free(t2);
4902
    if (unlikely(Rc(ctx->opcode) != 0))
4903
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4904
}
4905

    
4906
/* sre - sre. */
4907
static void gen_sre(DisasContext *ctx)
4908
{
4909
    TCGv t0 = tcg_temp_new();
4910
    TCGv t1 = tcg_temp_new();
4911
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4912
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4913
    tcg_gen_subfi_tl(t1, 32, t1);
4914
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4915
    tcg_gen_or_tl(t1, t0, t1);
4916
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4917
    gen_store_spr(SPR_MQ, t1);
4918
    tcg_temp_free(t0);
4919
    tcg_temp_free(t1);
4920
    if (unlikely(Rc(ctx->opcode) != 0))
4921
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4922
}
4923

    
4924
/* srea - srea. */
4925
static void gen_srea(DisasContext *ctx)
4926
{
4927
    TCGv t0 = tcg_temp_new();
4928
    TCGv t1 = tcg_temp_new();
4929
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4930
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4931
    gen_store_spr(SPR_MQ, t0);
4932
    tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
4933
    tcg_temp_free(t0);
4934
    tcg_temp_free(t1);
4935
    if (unlikely(Rc(ctx->opcode) != 0))
4936
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4937
}
4938

    
4939
/* sreq */
4940
static void gen_sreq(DisasContext *ctx)
4941
{
4942
    TCGv t0 = tcg_temp_new();
4943
    TCGv t1 = tcg_temp_new();
4944
    TCGv t2 = tcg_temp_new();
4945
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4946
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4947
    tcg_gen_shr_tl(t1, t1, t0);
4948
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4949
    gen_load_spr(t2, SPR_MQ);
4950
    gen_store_spr(SPR_MQ, t0);
4951
    tcg_gen_and_tl(t0, t0, t1);
4952
    tcg_gen_andc_tl(t2, t2, t1);
4953
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4954
    tcg_temp_free(t0);
4955
    tcg_temp_free(t1);
4956
    tcg_temp_free(t2);
4957
    if (unlikely(Rc(ctx->opcode) != 0))
4958
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4959
}
4960

    
4961
/* sriq */
4962
static void gen_sriq(DisasContext *ctx)
4963
{
4964
    int sh = SH(ctx->opcode);
4965
    TCGv t0 = tcg_temp_new();
4966
    TCGv t1 = tcg_temp_new();
4967
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4968
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4969
    tcg_gen_or_tl(t1, t0, t1);
4970
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4971
    gen_store_spr(SPR_MQ, t1);
4972
    tcg_temp_free(t0);
4973
    tcg_temp_free(t1);
4974
    if (unlikely(Rc(ctx->opcode) != 0))
4975
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4976
}
4977

    
4978
/* srliq */
4979
static void gen_srliq(DisasContext *ctx)
4980
{
4981
    int sh = SH(ctx->opcode);
4982
    TCGv t0 = tcg_temp_new();
4983
    TCGv t1 = tcg_temp_new();
4984
    tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4985
    gen_load_spr(t1, SPR_MQ);
4986
    gen_store_spr(SPR_MQ, t0);
4987
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU >> sh));
4988
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
4989
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4990
    tcg_temp_free(t0);
4991
    tcg_temp_free(t1);
4992
    if (unlikely(Rc(ctx->opcode) != 0))
4993
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4994
}
4995

    
4996
/* srlq */
4997
static void gen_srlq(DisasContext *ctx)
4998
{
4999
    int l1 = gen_new_label();
5000
    int l2 = gen_new_label();
5001
    TCGv t0 = tcg_temp_local_new();
5002
    TCGv t1 = tcg_temp_local_new();
5003
    TCGv t2 = tcg_temp_local_new();
5004
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5005
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5006
    tcg_gen_shr_tl(t2, t1, t2);
5007
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5008
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5009
    gen_load_spr(t0, SPR_MQ);
5010
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5011
    tcg_gen_br(l2);
5012
    gen_set_label(l1);
5013
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5014
    tcg_gen_and_tl(t0, t0, t2);
5015
    gen_load_spr(t1, SPR_MQ);
5016
    tcg_gen_andc_tl(t1, t1, t2);
5017
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5018