Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (285.9 kB)

1 79aceca5 bellard
/*
2 3fc6c082 bellard
 *  PowerPC emulation for qemu: main translation routines.
3 5fafdf24 ths
 *
4 76a66253 j_mayer
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5 79aceca5 bellard
 *
6 79aceca5 bellard
 * This library is free software; you can redistribute it and/or
7 79aceca5 bellard
 * modify it under the terms of the GNU Lesser General Public
8 79aceca5 bellard
 * License as published by the Free Software Foundation; either
9 79aceca5 bellard
 * version 2 of the License, or (at your option) any later version.
10 79aceca5 bellard
 *
11 79aceca5 bellard
 * This library is distributed in the hope that it will be useful,
12 79aceca5 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 79aceca5 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 79aceca5 bellard
 * Lesser General Public License for more details.
15 79aceca5 bellard
 *
16 79aceca5 bellard
 * You should have received a copy of the GNU Lesser General Public
17 79aceca5 bellard
 * License along with this library; if not, write to the Free Software
18 79aceca5 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 79aceca5 bellard
 */
20 c6a1c22b bellard
#include <stdarg.h>
21 c6a1c22b bellard
#include <stdlib.h>
22 c6a1c22b bellard
#include <stdio.h>
23 c6a1c22b bellard
#include <string.h>
24 c6a1c22b bellard
#include <inttypes.h>
25 c6a1c22b bellard
26 79aceca5 bellard
#include "cpu.h"
27 c6a1c22b bellard
#include "exec-all.h"
28 79aceca5 bellard
#include "disas.h"
29 57fec1fe bellard
#include "tcg-op.h"
30 ca10f867 aurel32
#include "qemu-common.h"
31 79aceca5 bellard
32 a7812ae4 pbrook
#include "helper.h"
33 a7812ae4 pbrook
#define GEN_HELPER 1
34 a7812ae4 pbrook
#include "helper.h"
35 a7812ae4 pbrook
36 8cbcb4fa aurel32
#define CPU_SINGLE_STEP 0x1
37 8cbcb4fa aurel32
#define CPU_BRANCH_STEP 0x2
38 8cbcb4fa aurel32
#define GDBSTUB_SINGLE_STEP 0x4
39 8cbcb4fa aurel32
40 a750fc0b j_mayer
/* Include definitions for instructions classes and implementations flags */
41 e8fc4fa7 aurel32
//#define DO_SINGLE_STEP
42 9fddaa0c bellard
//#define PPC_DEBUG_DISAS
43 76a66253 j_mayer
//#define DO_PPC_STATISTICS
44 7c58044c j_mayer
//#define OPTIMIZE_FPRF_UPDATE
45 79aceca5 bellard
46 a750fc0b j_mayer
/*****************************************************************************/
47 a750fc0b j_mayer
/* Code translation helpers                                                  */
48 c53be334 bellard
49 f78fb44e aurel32
/* global register indexes */
50 a7812ae4 pbrook
static TCGv_ptr cpu_env;
51 1d542695 aurel32
static char cpu_reg_names[10*3 + 22*4 /* GPR */
52 f78fb44e aurel32
#if !defined(TARGET_PPC64)
53 1d542695 aurel32
    + 10*4 + 22*5 /* SPE GPRh */
54 f78fb44e aurel32
#endif
55 a5e26afa aurel32
    + 10*4 + 22*5 /* FPR */
56 47e4661c aurel32
    + 2*(10*6 + 22*7) /* AVRh, AVRl */
57 47e4661c aurel32
    + 8*5 /* CRF */];
58 f78fb44e aurel32
static TCGv cpu_gpr[32];
59 f78fb44e aurel32
#if !defined(TARGET_PPC64)
60 f78fb44e aurel32
static TCGv cpu_gprh[32];
61 f78fb44e aurel32
#endif
62 a7812ae4 pbrook
static TCGv_i64 cpu_fpr[32];
63 a7812ae4 pbrook
static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
64 a7812ae4 pbrook
static TCGv_i32 cpu_crf[8];
65 bd568f18 aurel32
static TCGv cpu_nip;
66 6527f6ea aurel32
static TCGv cpu_msr;
67 cfdcd37a aurel32
static TCGv cpu_ctr;
68 cfdcd37a aurel32
static TCGv cpu_lr;
69 3d7b417e aurel32
static TCGv cpu_xer;
70 cf360a32 aurel32
static TCGv cpu_reserve;
71 a7812ae4 pbrook
static TCGv_i32 cpu_fpscr;
72 a7859e89 aurel32
static TCGv_i32 cpu_access_type;
73 f78fb44e aurel32
74 2e70f6ef pbrook
#include "gen-icount.h"
75 2e70f6ef pbrook
76 2e70f6ef pbrook
void ppc_translate_init(void)
77 2e70f6ef pbrook
{
78 f78fb44e aurel32
    int i;
79 f78fb44e aurel32
    char* p;
80 b2437bf2 pbrook
    static int done_init = 0;
81 f78fb44e aurel32
82 2e70f6ef pbrook
    if (done_init)
83 2e70f6ef pbrook
        return;
84 f78fb44e aurel32
85 a7812ae4 pbrook
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
86 a7812ae4 pbrook
87 f78fb44e aurel32
    p = cpu_reg_names;
88 47e4661c aurel32
89 47e4661c aurel32
    for (i = 0; i < 8; i++) {
90 47e4661c aurel32
        sprintf(p, "crf%d", i);
91 a7812ae4 pbrook
        cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
92 a7812ae4 pbrook
                                            offsetof(CPUState, crf[i]), p);
93 47e4661c aurel32
        p += 5;
94 47e4661c aurel32
    }
95 47e4661c aurel32
96 f78fb44e aurel32
    for (i = 0; i < 32; i++) {
97 f78fb44e aurel32
        sprintf(p, "r%d", i);
98 a7812ae4 pbrook
        cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
99 f78fb44e aurel32
                                        offsetof(CPUState, gpr[i]), p);
100 f78fb44e aurel32
        p += (i < 10) ? 3 : 4;
101 f78fb44e aurel32
#if !defined(TARGET_PPC64)
102 f78fb44e aurel32
        sprintf(p, "r%dH", i);
103 a7812ae4 pbrook
        cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
104 a7812ae4 pbrook
                                             offsetof(CPUState, gprh[i]), p);
105 f78fb44e aurel32
        p += (i < 10) ? 4 : 5;
106 f78fb44e aurel32
#endif
107 1d542695 aurel32
108 a5e26afa aurel32
        sprintf(p, "fp%d", i);
109 a7812ae4 pbrook
        cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
110 a7812ae4 pbrook
                                            offsetof(CPUState, fpr[i]), p);
111 ec1ac72d aurel32
        p += (i < 10) ? 4 : 5;
112 a5e26afa aurel32
113 1d542695 aurel32
        sprintf(p, "avr%dH", i);
114 fe1e5c53 aurel32
#ifdef WORDS_BIGENDIAN
115 fe1e5c53 aurel32
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
116 fe1e5c53 aurel32
                                             offsetof(CPUState, avr[i].u64[0]), p);
117 fe1e5c53 aurel32
#else
118 a7812ae4 pbrook
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
119 fe1e5c53 aurel32
                                             offsetof(CPUState, avr[i].u64[1]), p);
120 fe1e5c53 aurel32
#endif
121 1d542695 aurel32
        p += (i < 10) ? 6 : 7;
122 ec1ac72d aurel32
123 1d542695 aurel32
        sprintf(p, "avr%dL", i);
124 fe1e5c53 aurel32
#ifdef WORDS_BIGENDIAN
125 fe1e5c53 aurel32
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
126 fe1e5c53 aurel32
                                             offsetof(CPUState, avr[i].u64[1]), p);
127 fe1e5c53 aurel32
#else
128 a7812ae4 pbrook
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
129 fe1e5c53 aurel32
                                             offsetof(CPUState, avr[i].u64[0]), p);
130 fe1e5c53 aurel32
#endif
131 1d542695 aurel32
        p += (i < 10) ? 6 : 7;
132 f78fb44e aurel32
    }
133 f10dc08e aurel32
134 a7812ae4 pbrook
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
135 bd568f18 aurel32
                                 offsetof(CPUState, nip), "nip");
136 bd568f18 aurel32
137 6527f6ea aurel32
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
138 6527f6ea aurel32
                                 offsetof(CPUState, msr), "msr");
139 6527f6ea aurel32
140 a7812ae4 pbrook
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
141 cfdcd37a aurel32
                                 offsetof(CPUState, ctr), "ctr");
142 cfdcd37a aurel32
143 a7812ae4 pbrook
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
144 cfdcd37a aurel32
                                offsetof(CPUState, lr), "lr");
145 cfdcd37a aurel32
146 a7812ae4 pbrook
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
147 3d7b417e aurel32
                                 offsetof(CPUState, xer), "xer");
148 3d7b417e aurel32
149 cf360a32 aurel32
    cpu_reserve = tcg_global_mem_new(TCG_AREG0,
150 cf360a32 aurel32
                                     offsetof(CPUState, reserve), "reserve");
151 cf360a32 aurel32
152 a7812ae4 pbrook
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
153 a7812ae4 pbrook
                                       offsetof(CPUState, fpscr), "fpscr");
154 e1571908 aurel32
155 a7859e89 aurel32
    cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
156 a7859e89 aurel32
                                             offsetof(CPUState, access_type), "access_type");
157 a7859e89 aurel32
158 f10dc08e aurel32
    /* register helpers */
159 a7812ae4 pbrook
#define GEN_HELPER 2
160 f10dc08e aurel32
#include "helper.h"
161 f10dc08e aurel32
162 2e70f6ef pbrook
    done_init = 1;
163 2e70f6ef pbrook
}
164 2e70f6ef pbrook
165 7c58044c j_mayer
#if defined(OPTIMIZE_FPRF_UPDATE)
166 7c58044c j_mayer
static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
167 7c58044c j_mayer
static uint16_t **gen_fprf_ptr;
168 7c58044c j_mayer
#endif
169 79aceca5 bellard
170 79aceca5 bellard
/* internal defines */
171 79aceca5 bellard
typedef struct DisasContext {
172 79aceca5 bellard
    struct TranslationBlock *tb;
173 0fa85d43 bellard
    target_ulong nip;
174 79aceca5 bellard
    uint32_t opcode;
175 9a64fbe4 bellard
    uint32_t exception;
176 3cc62370 bellard
    /* Routine used to access memory */
177 3cc62370 bellard
    int mem_idx;
178 76db3ba4 aurel32
    int access_type;
179 3cc62370 bellard
    /* Translation flags */
180 76db3ba4 aurel32
    int le_mode;
181 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
182 d9bce9d9 j_mayer
    int sf_mode;
183 d9bce9d9 j_mayer
#endif
184 3cc62370 bellard
    int fpu_enabled;
185 a9d9eb8f j_mayer
    int altivec_enabled;
186 0487d6a8 j_mayer
    int spe_enabled;
187 3fc6c082 bellard
    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
188 ea4e754f bellard
    int singlestep_enabled;
189 79aceca5 bellard
} DisasContext;
190 79aceca5 bellard
191 3fc6c082 bellard
struct opc_handler_t {
192 79aceca5 bellard
    /* invalid bits */
193 79aceca5 bellard
    uint32_t inval;
194 9a64fbe4 bellard
    /* instruction type */
195 0487d6a8 j_mayer
    uint64_t type;
196 79aceca5 bellard
    /* handler */
197 79aceca5 bellard
    void (*handler)(DisasContext *ctx);
198 a750fc0b j_mayer
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
199 b55266b5 blueswir1
    const char *oname;
200 a750fc0b j_mayer
#endif
201 a750fc0b j_mayer
#if defined(DO_PPC_STATISTICS)
202 76a66253 j_mayer
    uint64_t count;
203 76a66253 j_mayer
#endif
204 3fc6c082 bellard
};
205 79aceca5 bellard
206 7c58044c j_mayer
static always_inline void gen_reset_fpstatus (void)
207 7c58044c j_mayer
{
208 7c58044c j_mayer
#ifdef CONFIG_SOFTFLOAT
209 7c58044c j_mayer
    gen_op_reset_fpstatus();
210 7c58044c j_mayer
#endif
211 7c58044c j_mayer
}
212 7c58044c j_mayer
213 0f2f39c2 aurel32
static always_inline void gen_compute_fprf (TCGv_i64 arg, int set_fprf, int set_rc)
214 7c58044c j_mayer
{
215 0f2f39c2 aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();
216 af12906f aurel32
217 7c58044c j_mayer
    if (set_fprf != 0) {
218 7c58044c j_mayer
        /* This case might be optimized later */
219 7c58044c j_mayer
#if defined(OPTIMIZE_FPRF_UPDATE)
220 7c58044c j_mayer
        *gen_fprf_ptr++ = gen_opc_ptr;
221 7c58044c j_mayer
#endif
222 0f2f39c2 aurel32
        tcg_gen_movi_i32(t0, 1);
223 af12906f aurel32
        gen_helper_compute_fprf(t0, arg, t0);
224 a7812ae4 pbrook
        if (unlikely(set_rc)) {
225 0f2f39c2 aurel32
            tcg_gen_mov_i32(cpu_crf[1], t0);
226 a7812ae4 pbrook
        }
227 af12906f aurel32
        gen_helper_float_check_status();
228 7c58044c j_mayer
    } else if (unlikely(set_rc)) {
229 7c58044c j_mayer
        /* We always need to compute fpcc */
230 0f2f39c2 aurel32
        tcg_gen_movi_i32(t0, 0);
231 af12906f aurel32
        gen_helper_compute_fprf(t0, arg, t0);
232 0f2f39c2 aurel32
        tcg_gen_mov_i32(cpu_crf[1], t0);
233 7c58044c j_mayer
    }
234 af12906f aurel32
235 0f2f39c2 aurel32
    tcg_temp_free_i32(t0);
236 7c58044c j_mayer
}
237 7c58044c j_mayer
238 7c58044c j_mayer
static always_inline void gen_optimize_fprf (void)
239 7c58044c j_mayer
{
240 7c58044c j_mayer
#if defined(OPTIMIZE_FPRF_UPDATE)
241 7c58044c j_mayer
    uint16_t **ptr;
242 7c58044c j_mayer
243 7c58044c j_mayer
    for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
244 7c58044c j_mayer
        *ptr = INDEX_op_nop1;
245 7c58044c j_mayer
    gen_fprf_ptr = gen_fprf_buf;
246 7c58044c j_mayer
#endif
247 7c58044c j_mayer
}
248 7c58044c j_mayer
249 76db3ba4 aurel32
static always_inline void gen_set_access_type (DisasContext *ctx, int access_type)
250 a7859e89 aurel32
{
251 76db3ba4 aurel32
    if (ctx->access_type != access_type) {
252 76db3ba4 aurel32
        tcg_gen_movi_i32(cpu_access_type, access_type);
253 76db3ba4 aurel32
        ctx->access_type = access_type;
254 76db3ba4 aurel32
    }
255 a7859e89 aurel32
}
256 a7859e89 aurel32
257 b068d6a7 j_mayer
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
258 d9bce9d9 j_mayer
{
259 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
260 d9bce9d9 j_mayer
    if (ctx->sf_mode)
261 bd568f18 aurel32
        tcg_gen_movi_tl(cpu_nip, nip);
262 d9bce9d9 j_mayer
    else
263 d9bce9d9 j_mayer
#endif
264 bd568f18 aurel32
        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
265 d9bce9d9 j_mayer
}
266 d9bce9d9 j_mayer
267 e1833e1f j_mayer
#define GEN_EXCP(ctx, excp, error)                                            \
268 79aceca5 bellard
do {                                                                          \
269 64adab3f aurel32
    TCGv_i32 t0 = tcg_const_i32(excp);                                        \
270 64adab3f aurel32
    TCGv_i32 t1 = tcg_const_i32(error);                                       \
271 e1833e1f j_mayer
    if ((ctx)->exception == POWERPC_EXCP_NONE) {                              \
272 d9bce9d9 j_mayer
        gen_update_nip(ctx, (ctx)->nip);                                      \
273 9fddaa0c bellard
    }                                                                         \
274 64adab3f aurel32
    gen_helper_raise_exception_err(t0, t1);                                   \
275 64adab3f aurel32
    tcg_temp_free_i32(t0);                                                    \
276 64adab3f aurel32
    tcg_temp_free_i32(t1);                                                    \
277 9fddaa0c bellard
    ctx->exception = (excp);                                                  \
278 79aceca5 bellard
} while (0)
279 79aceca5 bellard
280 e1833e1f j_mayer
#define GEN_EXCP_INVAL(ctx)                                                   \
281 e1833e1f j_mayer
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
282 e1833e1f j_mayer
         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
283 9fddaa0c bellard
284 e1833e1f j_mayer
#define GEN_EXCP_PRIVOPC(ctx)                                                 \
285 e1833e1f j_mayer
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
286 e1833e1f j_mayer
         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
287 9a64fbe4 bellard
288 e1833e1f j_mayer
#define GEN_EXCP_PRIVREG(ctx)                                                 \
289 e1833e1f j_mayer
GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
290 e1833e1f j_mayer
         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)
291 e1833e1f j_mayer
292 e1833e1f j_mayer
#define GEN_EXCP_NO_FP(ctx)                                                   \
293 e1833e1f j_mayer
GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)
294 e1833e1f j_mayer
295 e1833e1f j_mayer
#define GEN_EXCP_NO_AP(ctx)                                                   \
296 e1833e1f j_mayer
GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
297 9a64fbe4 bellard
298 a9d9eb8f j_mayer
#define GEN_EXCP_NO_VR(ctx)                                                   \
299 a9d9eb8f j_mayer
GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)
300 a9d9eb8f j_mayer
301 f24e5695 bellard
/* Stop translation */
302 b068d6a7 j_mayer
static always_inline void GEN_STOP (DisasContext *ctx)
303 3fc6c082 bellard
{
304 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip);
305 e1833e1f j_mayer
    ctx->exception = POWERPC_EXCP_STOP;
306 3fc6c082 bellard
}
307 3fc6c082 bellard
308 f24e5695 bellard
/* No need to update nip here, as execution flow will change */
309 b068d6a7 j_mayer
static always_inline void GEN_SYNC (DisasContext *ctx)
310 2be0071f bellard
{
311 e1833e1f j_mayer
    ctx->exception = POWERPC_EXCP_SYNC;
312 2be0071f bellard
}
313 2be0071f bellard
314 79aceca5 bellard
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
315 79aceca5 bellard
static void gen_##name (DisasContext *ctx);                                   \
316 79aceca5 bellard
GEN_OPCODE(name, opc1, opc2, opc3, inval, type);                              \
317 79aceca5 bellard
static void gen_##name (DisasContext *ctx)
318 79aceca5 bellard
319 c7697e1f j_mayer
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
320 c7697e1f j_mayer
static void gen_##name (DisasContext *ctx);                                   \
321 c7697e1f j_mayer
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type);                       \
322 c7697e1f j_mayer
static void gen_##name (DisasContext *ctx)
323 c7697e1f j_mayer
324 79aceca5 bellard
typedef struct opcode_t {
325 79aceca5 bellard
    unsigned char opc1, opc2, opc3;
326 1235fc06 ths
#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
327 18fba28c bellard
    unsigned char pad[5];
328 18fba28c bellard
#else
329 18fba28c bellard
    unsigned char pad[1];
330 18fba28c bellard
#endif
331 79aceca5 bellard
    opc_handler_t handler;
332 b55266b5 blueswir1
    const char *oname;
333 79aceca5 bellard
} opcode_t;
334 79aceca5 bellard
335 a750fc0b j_mayer
/*****************************************************************************/
336 79aceca5 bellard
/***                           Instruction decoding                        ***/
337 79aceca5 bellard
#define EXTRACT_HELPER(name, shift, nb)                                       \
338 b068d6a7 j_mayer
static always_inline uint32_t name (uint32_t opcode)                          \
339 79aceca5 bellard
{                                                                             \
340 79aceca5 bellard
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
341 79aceca5 bellard
}
342 79aceca5 bellard
343 79aceca5 bellard
#define EXTRACT_SHELPER(name, shift, nb)                                      \
344 b068d6a7 j_mayer
static always_inline int32_t name (uint32_t opcode)                           \
345 79aceca5 bellard
{                                                                             \
346 18fba28c bellard
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
347 79aceca5 bellard
}
348 79aceca5 bellard
349 79aceca5 bellard
/* Opcode part 1 */
350 79aceca5 bellard
EXTRACT_HELPER(opc1, 26, 6);
351 79aceca5 bellard
/* Opcode part 2 */
352 79aceca5 bellard
EXTRACT_HELPER(opc2, 1, 5);
353 79aceca5 bellard
/* Opcode part 3 */
354 79aceca5 bellard
EXTRACT_HELPER(opc3, 6, 5);
355 79aceca5 bellard
/* Update Cr0 flags */
356 79aceca5 bellard
EXTRACT_HELPER(Rc, 0, 1);
357 79aceca5 bellard
/* Destination */
358 79aceca5 bellard
EXTRACT_HELPER(rD, 21, 5);
359 79aceca5 bellard
/* Source */
360 79aceca5 bellard
EXTRACT_HELPER(rS, 21, 5);
361 79aceca5 bellard
/* First operand */
362 79aceca5 bellard
EXTRACT_HELPER(rA, 16, 5);
363 79aceca5 bellard
/* Second operand */
364 79aceca5 bellard
EXTRACT_HELPER(rB, 11, 5);
365 79aceca5 bellard
/* Third operand */
366 79aceca5 bellard
EXTRACT_HELPER(rC, 6, 5);
367 79aceca5 bellard
/***                               Get CRn                                 ***/
368 79aceca5 bellard
EXTRACT_HELPER(crfD, 23, 3);
369 79aceca5 bellard
EXTRACT_HELPER(crfS, 18, 3);
370 79aceca5 bellard
EXTRACT_HELPER(crbD, 21, 5);
371 79aceca5 bellard
EXTRACT_HELPER(crbA, 16, 5);
372 79aceca5 bellard
EXTRACT_HELPER(crbB, 11, 5);
373 79aceca5 bellard
/* SPR / TBL */
374 3fc6c082 bellard
EXTRACT_HELPER(_SPR, 11, 10);
375 b068d6a7 j_mayer
static always_inline uint32_t SPR (uint32_t opcode)
376 3fc6c082 bellard
{
377 3fc6c082 bellard
    uint32_t sprn = _SPR(opcode);
378 3fc6c082 bellard
379 3fc6c082 bellard
    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
380 3fc6c082 bellard
}
381 79aceca5 bellard
/***                              Get constants                            ***/
382 79aceca5 bellard
EXTRACT_HELPER(IMM, 12, 8);
383 79aceca5 bellard
/* 16 bits signed immediate value */
384 79aceca5 bellard
EXTRACT_SHELPER(SIMM, 0, 16);
385 79aceca5 bellard
/* 16 bits unsigned immediate value */
386 79aceca5 bellard
EXTRACT_HELPER(UIMM, 0, 16);
387 79aceca5 bellard
/* Bit count */
388 79aceca5 bellard
EXTRACT_HELPER(NB, 11, 5);
389 79aceca5 bellard
/* Shift count */
390 79aceca5 bellard
EXTRACT_HELPER(SH, 11, 5);
391 79aceca5 bellard
/* Mask start */
392 79aceca5 bellard
EXTRACT_HELPER(MB, 6, 5);
393 79aceca5 bellard
/* Mask end */
394 79aceca5 bellard
EXTRACT_HELPER(ME, 1, 5);
395 fb0eaffc bellard
/* Trap operand */
396 fb0eaffc bellard
EXTRACT_HELPER(TO, 21, 5);
397 79aceca5 bellard
398 79aceca5 bellard
EXTRACT_HELPER(CRM, 12, 8);
399 79aceca5 bellard
EXTRACT_HELPER(FM, 17, 8);
400 79aceca5 bellard
EXTRACT_HELPER(SR, 16, 4);
401 e4bb997e aurel32
EXTRACT_HELPER(FPIMM, 12, 4);
402 fb0eaffc bellard
403 79aceca5 bellard
/***                            Jump target decoding                       ***/
404 79aceca5 bellard
/* Displacement */
405 79aceca5 bellard
EXTRACT_SHELPER(d, 0, 16);
406 79aceca5 bellard
/* Immediate address */
407 b068d6a7 j_mayer
static always_inline target_ulong LI (uint32_t opcode)
408 79aceca5 bellard
{
409 79aceca5 bellard
    return (opcode >> 0) & 0x03FFFFFC;
410 79aceca5 bellard
}
411 79aceca5 bellard
412 b068d6a7 j_mayer
static always_inline uint32_t BD (uint32_t opcode)
413 79aceca5 bellard
{
414 79aceca5 bellard
    return (opcode >> 0) & 0xFFFC;
415 79aceca5 bellard
}
416 79aceca5 bellard
417 79aceca5 bellard
EXTRACT_HELPER(BO, 21, 5);
418 79aceca5 bellard
EXTRACT_HELPER(BI, 16, 5);
419 79aceca5 bellard
/* Absolute/relative address */
420 79aceca5 bellard
EXTRACT_HELPER(AA, 1, 1);
421 79aceca5 bellard
/* Link */
422 79aceca5 bellard
EXTRACT_HELPER(LK, 0, 1);
423 79aceca5 bellard
424 79aceca5 bellard
/* Create a mask between <start> and <end> bits */
425 b068d6a7 j_mayer
static always_inline target_ulong MASK (uint32_t start, uint32_t end)
426 79aceca5 bellard
{
427 76a66253 j_mayer
    target_ulong ret;
428 79aceca5 bellard
429 76a66253 j_mayer
#if defined(TARGET_PPC64)
430 76a66253 j_mayer
    if (likely(start == 0)) {
431 6f2d8978 j_mayer
        ret = UINT64_MAX << (63 - end);
432 76a66253 j_mayer
    } else if (likely(end == 63)) {
433 6f2d8978 j_mayer
        ret = UINT64_MAX >> start;
434 76a66253 j_mayer
    }
435 76a66253 j_mayer
#else
436 76a66253 j_mayer
    if (likely(start == 0)) {
437 6f2d8978 j_mayer
        ret = UINT32_MAX << (31  - end);
438 76a66253 j_mayer
    } else if (likely(end == 31)) {
439 6f2d8978 j_mayer
        ret = UINT32_MAX >> start;
440 76a66253 j_mayer
    }
441 76a66253 j_mayer
#endif
442 76a66253 j_mayer
    else {
443 76a66253 j_mayer
        ret = (((target_ulong)(-1ULL)) >> (start)) ^
444 76a66253 j_mayer
            (((target_ulong)(-1ULL) >> (end)) >> 1);
445 76a66253 j_mayer
        if (unlikely(start > end))
446 76a66253 j_mayer
            return ~ret;
447 76a66253 j_mayer
    }
448 79aceca5 bellard
449 79aceca5 bellard
    return ret;
450 79aceca5 bellard
}
451 79aceca5 bellard
452 a750fc0b j_mayer
/*****************************************************************************/
453 a750fc0b j_mayer
/* PowerPC Instructions types definitions                                    */
454 a750fc0b j_mayer
enum {
455 1b413d55 j_mayer
    PPC_NONE           = 0x0000000000000000ULL,
456 12de9a39 j_mayer
    /* PowerPC base instructions set                                         */
457 1b413d55 j_mayer
    PPC_INSNS_BASE     = 0x0000000000000001ULL,
458 1b413d55 j_mayer
    /*   integer operations instructions                                     */
459 a750fc0b j_mayer
#define PPC_INTEGER PPC_INSNS_BASE
460 1b413d55 j_mayer
    /*   flow control instructions                                           */
461 a750fc0b j_mayer
#define PPC_FLOW    PPC_INSNS_BASE
462 1b413d55 j_mayer
    /*   virtual memory instructions                                         */
463 a750fc0b j_mayer
#define PPC_MEM     PPC_INSNS_BASE
464 1b413d55 j_mayer
    /*   ld/st with reservation instructions                                 */
465 a750fc0b j_mayer
#define PPC_RES     PPC_INSNS_BASE
466 1b413d55 j_mayer
    /*   spr/msr access instructions                                         */
467 a750fc0b j_mayer
#define PPC_MISC    PPC_INSNS_BASE
468 1b413d55 j_mayer
    /* Deprecated instruction sets                                           */
469 1b413d55 j_mayer
    /*   Original POWER instruction set                                      */
470 f610349f j_mayer
    PPC_POWER          = 0x0000000000000002ULL,
471 1b413d55 j_mayer
    /*   POWER2 instruction set extension                                    */
472 f610349f j_mayer
    PPC_POWER2         = 0x0000000000000004ULL,
473 1b413d55 j_mayer
    /*   Power RTC support                                                   */
474 f610349f j_mayer
    PPC_POWER_RTC      = 0x0000000000000008ULL,
475 1b413d55 j_mayer
    /*   Power-to-PowerPC bridge (601)                                       */
476 f610349f j_mayer
    PPC_POWER_BR       = 0x0000000000000010ULL,
477 1b413d55 j_mayer
    /* 64 bits PowerPC instruction set                                       */
478 f610349f j_mayer
    PPC_64B            = 0x0000000000000020ULL,
479 1b413d55 j_mayer
    /*   New 64 bits extensions (PowerPC 2.0x)                               */
480 f610349f j_mayer
    PPC_64BX           = 0x0000000000000040ULL,
481 1b413d55 j_mayer
    /*   64 bits hypervisor extensions                                       */
482 f610349f j_mayer
    PPC_64H            = 0x0000000000000080ULL,
483 1b413d55 j_mayer
    /*   New wait instruction (PowerPC 2.0x)                                 */
484 f610349f j_mayer
    PPC_WAIT           = 0x0000000000000100ULL,
485 1b413d55 j_mayer
    /*   Time base mftb instruction                                          */
486 f610349f j_mayer
    PPC_MFTB           = 0x0000000000000200ULL,
487 1b413d55 j_mayer
488 1b413d55 j_mayer
    /* Fixed-point unit extensions                                           */
489 1b413d55 j_mayer
    /*   PowerPC 602 specific                                                */
490 f610349f j_mayer
    PPC_602_SPEC       = 0x0000000000000400ULL,
491 05332d70 j_mayer
    /*   isel instruction                                                    */
492 05332d70 j_mayer
    PPC_ISEL           = 0x0000000000000800ULL,
493 05332d70 j_mayer
    /*   popcntb instruction                                                 */
494 05332d70 j_mayer
    PPC_POPCNTB        = 0x0000000000001000ULL,
495 05332d70 j_mayer
    /*   string load / store                                                 */
496 05332d70 j_mayer
    PPC_STRING         = 0x0000000000002000ULL,
497 1b413d55 j_mayer
498 1b413d55 j_mayer
    /* Floating-point unit extensions                                        */
499 1b413d55 j_mayer
    /*   Optional floating point instructions                                */
500 1b413d55 j_mayer
    PPC_FLOAT          = 0x0000000000010000ULL,
501 1b413d55 j_mayer
    /* New floating-point extensions (PowerPC 2.0x)                          */
502 1b413d55 j_mayer
    PPC_FLOAT_EXT      = 0x0000000000020000ULL,
503 1b413d55 j_mayer
    PPC_FLOAT_FSQRT    = 0x0000000000040000ULL,
504 1b413d55 j_mayer
    PPC_FLOAT_FRES     = 0x0000000000080000ULL,
505 1b413d55 j_mayer
    PPC_FLOAT_FRSQRTE  = 0x0000000000100000ULL,
506 1b413d55 j_mayer
    PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
507 1b413d55 j_mayer
    PPC_FLOAT_FSEL     = 0x0000000000400000ULL,
508 1b413d55 j_mayer
    PPC_FLOAT_STFIWX   = 0x0000000000800000ULL,
509 1b413d55 j_mayer
510 1b413d55 j_mayer
    /* Vector/SIMD extensions                                                */
511 1b413d55 j_mayer
    /*   Altivec support                                                     */
512 1b413d55 j_mayer
    PPC_ALTIVEC        = 0x0000000001000000ULL,
513 1b413d55 j_mayer
    /*   PowerPC 2.03 SPE extension                                          */
514 05332d70 j_mayer
    PPC_SPE            = 0x0000000002000000ULL,
515 1b413d55 j_mayer
    /*   PowerPC 2.03 SPE floating-point extension                           */
516 05332d70 j_mayer
    PPC_SPEFPU         = 0x0000000004000000ULL,
517 1b413d55 j_mayer
518 12de9a39 j_mayer
    /* Optional memory control instructions                                  */
519 1b413d55 j_mayer
    PPC_MEM_TLBIA      = 0x0000000010000000ULL,
520 1b413d55 j_mayer
    PPC_MEM_TLBIE      = 0x0000000020000000ULL,
521 1b413d55 j_mayer
    PPC_MEM_TLBSYNC    = 0x0000000040000000ULL,
522 1b413d55 j_mayer
    /*   sync instruction                                                    */
523 1b413d55 j_mayer
    PPC_MEM_SYNC       = 0x0000000080000000ULL,
524 1b413d55 j_mayer
    /*   eieio instruction                                                   */
525 1b413d55 j_mayer
    PPC_MEM_EIEIO      = 0x0000000100000000ULL,
526 1b413d55 j_mayer
527 1b413d55 j_mayer
    /* Cache control instructions                                            */
528 c8623f2e j_mayer
    PPC_CACHE          = 0x0000000200000000ULL,
529 1b413d55 j_mayer
    /*   icbi instruction                                                    */
530 05332d70 j_mayer
    PPC_CACHE_ICBI     = 0x0000000400000000ULL,
531 1b413d55 j_mayer
    /*   dcbz instruction with fixed cache line size                         */
532 05332d70 j_mayer
    PPC_CACHE_DCBZ     = 0x0000000800000000ULL,
533 1b413d55 j_mayer
    /*   dcbz instruction with tunable cache line size                       */
534 05332d70 j_mayer
    PPC_CACHE_DCBZT    = 0x0000001000000000ULL,
535 1b413d55 j_mayer
    /*   dcba instruction                                                    */
536 05332d70 j_mayer
    PPC_CACHE_DCBA     = 0x0000002000000000ULL,
537 05332d70 j_mayer
    /*   Freescale cache locking instructions                                */
538 05332d70 j_mayer
    PPC_CACHE_LOCK     = 0x0000004000000000ULL,
539 1b413d55 j_mayer
540 1b413d55 j_mayer
    /* MMU related extensions                                                */
541 1b413d55 j_mayer
    /*   external control instructions                                       */
542 05332d70 j_mayer
    PPC_EXTERN         = 0x0000010000000000ULL,
543 1b413d55 j_mayer
    /*   segment register access instructions                                */
544 05332d70 j_mayer
    PPC_SEGMENT        = 0x0000020000000000ULL,
545 1b413d55 j_mayer
    /*   PowerPC 6xx TLB management instructions                             */
546 05332d70 j_mayer
    PPC_6xx_TLB        = 0x0000040000000000ULL,
547 1b413d55 j_mayer
    /* PowerPC 74xx TLB management instructions                              */
548 05332d70 j_mayer
    PPC_74xx_TLB       = 0x0000080000000000ULL,
549 1b413d55 j_mayer
    /*   PowerPC 40x TLB management instructions                             */
550 05332d70 j_mayer
    PPC_40x_TLB        = 0x0000100000000000ULL,
551 1b413d55 j_mayer
    /*   segment register access instructions for PowerPC 64 "bridge"        */
552 05332d70 j_mayer
    PPC_SEGMENT_64B    = 0x0000200000000000ULL,
553 1b413d55 j_mayer
    /*   SLB management                                                      */
554 05332d70 j_mayer
    PPC_SLBI           = 0x0000400000000000ULL,
555 1b413d55 j_mayer
556 12de9a39 j_mayer
    /* Embedded PowerPC dedicated instructions                               */
557 05332d70 j_mayer
    PPC_WRTEE          = 0x0001000000000000ULL,
558 12de9a39 j_mayer
    /* PowerPC 40x exception model                                           */
559 05332d70 j_mayer
    PPC_40x_EXCP       = 0x0002000000000000ULL,
560 12de9a39 j_mayer
    /* PowerPC 405 Mac instructions                                          */
561 05332d70 j_mayer
    PPC_405_MAC        = 0x0004000000000000ULL,
562 12de9a39 j_mayer
    /* PowerPC 440 specific instructions                                     */
563 05332d70 j_mayer
    PPC_440_SPEC       = 0x0008000000000000ULL,
564 12de9a39 j_mayer
    /* BookE (embedded) PowerPC specification                                */
565 05332d70 j_mayer
    PPC_BOOKE          = 0x0010000000000000ULL,
566 05332d70 j_mayer
    /* mfapidi instruction                                                   */
567 05332d70 j_mayer
    PPC_MFAPIDI        = 0x0020000000000000ULL,
568 05332d70 j_mayer
    /* tlbiva instruction                                                    */
569 05332d70 j_mayer
    PPC_TLBIVA         = 0x0040000000000000ULL,
570 05332d70 j_mayer
    /* tlbivax instruction                                                   */
571 05332d70 j_mayer
    PPC_TLBIVAX        = 0x0080000000000000ULL,
572 12de9a39 j_mayer
    /* PowerPC 4xx dedicated instructions                                    */
573 05332d70 j_mayer
    PPC_4xx_COMMON     = 0x0100000000000000ULL,
574 12de9a39 j_mayer
    /* PowerPC 40x ibct instructions                                         */
575 05332d70 j_mayer
    PPC_40x_ICBT       = 0x0200000000000000ULL,
576 12de9a39 j_mayer
    /* rfmci is not implemented in all BookE PowerPC                         */
577 05332d70 j_mayer
    PPC_RFMCI          = 0x0400000000000000ULL,
578 05332d70 j_mayer
    /* rfdi instruction                                                      */
579 05332d70 j_mayer
    PPC_RFDI           = 0x0800000000000000ULL,
580 05332d70 j_mayer
    /* DCR accesses                                                          */
581 05332d70 j_mayer
    PPC_DCR            = 0x1000000000000000ULL,
582 05332d70 j_mayer
    /* DCR extended accesse                                                  */
583 05332d70 j_mayer
    PPC_DCRX           = 0x2000000000000000ULL,
584 12de9a39 j_mayer
    /* user-mode DCR access, implemented in PowerPC 460                      */
585 05332d70 j_mayer
    PPC_DCRUX          = 0x4000000000000000ULL,
586 a750fc0b j_mayer
};
587 a750fc0b j_mayer
588 a750fc0b j_mayer
/*****************************************************************************/
589 a750fc0b j_mayer
/* PowerPC instructions table                                                */
590 3fc6c082 bellard
#if HOST_LONG_BITS == 64
591 3fc6c082 bellard
#define OPC_ALIGN 8
592 3fc6c082 bellard
#else
593 3fc6c082 bellard
#define OPC_ALIGN 4
594 3fc6c082 bellard
#endif
595 1b039c09 bellard
#if defined(__APPLE__)
596 d9bce9d9 j_mayer
#define OPCODES_SECTION                                                       \
597 3fc6c082 bellard
    __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
598 933dc6eb bellard
#else
599 d9bce9d9 j_mayer
#define OPCODES_SECTION                                                       \
600 3fc6c082 bellard
    __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
601 933dc6eb bellard
#endif
602 933dc6eb bellard
603 76a66253 j_mayer
#if defined(DO_PPC_STATISTICS)
604 79aceca5 bellard
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
605 18fba28c bellard
OPCODES_SECTION opcode_t opc_##name = {                                       \
606 79aceca5 bellard
    .opc1 = op1,                                                              \
607 79aceca5 bellard
    .opc2 = op2,                                                              \
608 79aceca5 bellard
    .opc3 = op3,                                                              \
609 18fba28c bellard
    .pad  = { 0, },                                                           \
610 79aceca5 bellard
    .handler = {                                                              \
611 79aceca5 bellard
        .inval   = invl,                                                      \
612 9a64fbe4 bellard
        .type = _typ,                                                         \
613 79aceca5 bellard
        .handler = &gen_##name,                                               \
614 76a66253 j_mayer
        .oname = stringify(name),                                             \
615 79aceca5 bellard
    },                                                                        \
616 3fc6c082 bellard
    .oname = stringify(name),                                                 \
617 79aceca5 bellard
}
618 c7697e1f j_mayer
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
619 c7697e1f j_mayer
OPCODES_SECTION opcode_t opc_##name = {                                       \
620 c7697e1f j_mayer
    .opc1 = op1,                                                              \
621 c7697e1f j_mayer
    .opc2 = op2,                                                              \
622 c7697e1f j_mayer
    .opc3 = op3,                                                              \
623 c7697e1f j_mayer
    .pad  = { 0, },                                                           \
624 c7697e1f j_mayer
    .handler = {                                                              \
625 c7697e1f j_mayer
        .inval   = invl,                                                      \
626 c7697e1f j_mayer
        .type = _typ,                                                         \
627 c7697e1f j_mayer
        .handler = &gen_##name,                                               \
628 c7697e1f j_mayer
        .oname = onam,                                                        \
629 c7697e1f j_mayer
    },                                                                        \
630 c7697e1f j_mayer
    .oname = onam,                                                            \
631 c7697e1f j_mayer
}
632 76a66253 j_mayer
#else
633 76a66253 j_mayer
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
634 76a66253 j_mayer
OPCODES_SECTION opcode_t opc_##name = {                                       \
635 76a66253 j_mayer
    .opc1 = op1,                                                              \
636 76a66253 j_mayer
    .opc2 = op2,                                                              \
637 76a66253 j_mayer
    .opc3 = op3,                                                              \
638 76a66253 j_mayer
    .pad  = { 0, },                                                           \
639 76a66253 j_mayer
    .handler = {                                                              \
640 76a66253 j_mayer
        .inval   = invl,                                                      \
641 76a66253 j_mayer
        .type = _typ,                                                         \
642 76a66253 j_mayer
        .handler = &gen_##name,                                               \
643 76a66253 j_mayer
    },                                                                        \
644 76a66253 j_mayer
    .oname = stringify(name),                                                 \
645 76a66253 j_mayer
}
646 c7697e1f j_mayer
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ)                    \
647 c7697e1f j_mayer
OPCODES_SECTION opcode_t opc_##name = {                                       \
648 c7697e1f j_mayer
    .opc1 = op1,                                                              \
649 c7697e1f j_mayer
    .opc2 = op2,                                                              \
650 c7697e1f j_mayer
    .opc3 = op3,                                                              \
651 c7697e1f j_mayer
    .pad  = { 0, },                                                           \
652 c7697e1f j_mayer
    .handler = {                                                              \
653 c7697e1f j_mayer
        .inval   = invl,                                                      \
654 c7697e1f j_mayer
        .type = _typ,                                                         \
655 c7697e1f j_mayer
        .handler = &gen_##name,                                               \
656 c7697e1f j_mayer
    },                                                                        \
657 c7697e1f j_mayer
    .oname = onam,                                                            \
658 c7697e1f j_mayer
}
659 76a66253 j_mayer
#endif
660 79aceca5 bellard
661 79aceca5 bellard
#define GEN_OPCODE_MARK(name)                                                 \
662 18fba28c bellard
OPCODES_SECTION opcode_t opc_##name = {                                       \
663 79aceca5 bellard
    .opc1 = 0xFF,                                                             \
664 79aceca5 bellard
    .opc2 = 0xFF,                                                             \
665 79aceca5 bellard
    .opc3 = 0xFF,                                                             \
666 18fba28c bellard
    .pad  = { 0, },                                                           \
667 79aceca5 bellard
    .handler = {                                                              \
668 79aceca5 bellard
        .inval   = 0x00000000,                                                \
669 9a64fbe4 bellard
        .type = 0x00,                                                         \
670 79aceca5 bellard
        .handler = NULL,                                                      \
671 79aceca5 bellard
    },                                                                        \
672 3fc6c082 bellard
    .oname = stringify(name),                                                 \
673 79aceca5 bellard
}
674 79aceca5 bellard
675 54cdcae6 aurel32
/* SPR load/store helpers */
676 54cdcae6 aurel32
static always_inline void gen_load_spr(TCGv t, int reg)
677 54cdcae6 aurel32
{
678 54cdcae6 aurel32
    tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
679 54cdcae6 aurel32
}
680 54cdcae6 aurel32
681 54cdcae6 aurel32
static always_inline void gen_store_spr(int reg, TCGv t)
682 54cdcae6 aurel32
{
683 54cdcae6 aurel32
    tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
684 54cdcae6 aurel32
}
685 54cdcae6 aurel32
686 79aceca5 bellard
/* Start opcode list */
687 79aceca5 bellard
GEN_OPCODE_MARK(start);
688 79aceca5 bellard
689 79aceca5 bellard
/* Invalid instruction */
690 9a64fbe4 bellard
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
691 9a64fbe4 bellard
{
692 e1833e1f j_mayer
    GEN_EXCP_INVAL(ctx);
693 9a64fbe4 bellard
}
694 9a64fbe4 bellard
695 79aceca5 bellard
static opc_handler_t invalid_handler = {
696 79aceca5 bellard
    .inval   = 0xFFFFFFFF,
697 9a64fbe4 bellard
    .type    = PPC_NONE,
698 79aceca5 bellard
    .handler = gen_invalid,
699 79aceca5 bellard
};
700 79aceca5 bellard
701 e1571908 aurel32
/***                           Integer comparison                          ***/
702 e1571908 aurel32
703 ea363694 aurel32
static always_inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
704 e1571908 aurel32
{
705 e1571908 aurel32
    int l1, l2, l3;
706 e1571908 aurel32
707 269f3e95 aurel32
    tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
708 269f3e95 aurel32
    tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
709 e1571908 aurel32
    tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);
710 e1571908 aurel32
711 e1571908 aurel32
    l1 = gen_new_label();
712 e1571908 aurel32
    l2 = gen_new_label();
713 e1571908 aurel32
    l3 = gen_new_label();
714 e1571908 aurel32
    if (s) {
715 ea363694 aurel32
        tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
716 ea363694 aurel32
        tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
717 e1571908 aurel32
    } else {
718 ea363694 aurel32
        tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
719 ea363694 aurel32
        tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
720 e1571908 aurel32
    }
721 e1571908 aurel32
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
722 e1571908 aurel32
    tcg_gen_br(l3);
723 e1571908 aurel32
    gen_set_label(l1);
724 e1571908 aurel32
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
725 e1571908 aurel32
    tcg_gen_br(l3);
726 e1571908 aurel32
    gen_set_label(l2);
727 e1571908 aurel32
    tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
728 e1571908 aurel32
    gen_set_label(l3);
729 e1571908 aurel32
}
730 e1571908 aurel32
731 ea363694 aurel32
static always_inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
732 e1571908 aurel32
{
733 ea363694 aurel32
    TCGv t0 = tcg_const_local_tl(arg1);
734 ea363694 aurel32
    gen_op_cmp(arg0, t0, s, crf);
735 ea363694 aurel32
    tcg_temp_free(t0);
736 e1571908 aurel32
}
737 e1571908 aurel32
738 e1571908 aurel32
#if defined(TARGET_PPC64)
739 ea363694 aurel32
static always_inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
740 e1571908 aurel32
{
741 ea363694 aurel32
    TCGv t0, t1;
742 a7812ae4 pbrook
    t0 = tcg_temp_local_new();
743 a7812ae4 pbrook
    t1 = tcg_temp_local_new();
744 e1571908 aurel32
    if (s) {
745 ea363694 aurel32
        tcg_gen_ext32s_tl(t0, arg0);
746 ea363694 aurel32
        tcg_gen_ext32s_tl(t1, arg1);
747 e1571908 aurel32
    } else {
748 ea363694 aurel32
        tcg_gen_ext32u_tl(t0, arg0);
749 ea363694 aurel32
        tcg_gen_ext32u_tl(t1, arg1);
750 e1571908 aurel32
    }
751 ea363694 aurel32
    gen_op_cmp(t0, t1, s, crf);
752 ea363694 aurel32
    tcg_temp_free(t1);
753 ea363694 aurel32
    tcg_temp_free(t0);
754 e1571908 aurel32
}
755 e1571908 aurel32
756 ea363694 aurel32
static always_inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
757 e1571908 aurel32
{
758 ea363694 aurel32
    TCGv t0 = tcg_const_local_tl(arg1);
759 ea363694 aurel32
    gen_op_cmp32(arg0, t0, s, crf);
760 ea363694 aurel32
    tcg_temp_free(t0);
761 e1571908 aurel32
}
762 e1571908 aurel32
#endif
763 e1571908 aurel32
764 e1571908 aurel32
static always_inline void gen_set_Rc0 (DisasContext *ctx, TCGv reg)
765 e1571908 aurel32
{
766 e1571908 aurel32
#if defined(TARGET_PPC64)
767 e1571908 aurel32
    if (!(ctx->sf_mode))
768 e1571908 aurel32
        gen_op_cmpi32(reg, 0, 1, 0);
769 e1571908 aurel32
    else
770 e1571908 aurel32
#endif
771 e1571908 aurel32
        gen_op_cmpi(reg, 0, 1, 0);
772 e1571908 aurel32
}
773 e1571908 aurel32
774 e1571908 aurel32
/* cmp */
775 e1571908 aurel32
GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER)
776 e1571908 aurel32
{
777 e1571908 aurel32
#if defined(TARGET_PPC64)
778 e1571908 aurel32
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
779 e1571908 aurel32
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
780 e1571908 aurel32
                     1, crfD(ctx->opcode));
781 e1571908 aurel32
    else
782 e1571908 aurel32
#endif
783 e1571908 aurel32
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
784 e1571908 aurel32
                   1, crfD(ctx->opcode));
785 e1571908 aurel32
}
786 e1571908 aurel32
787 e1571908 aurel32
/* cmpi */
788 e1571908 aurel32
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
789 e1571908 aurel32
{
790 e1571908 aurel32
#if defined(TARGET_PPC64)
791 e1571908 aurel32
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
792 e1571908 aurel32
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
793 e1571908 aurel32
                      1, crfD(ctx->opcode));
794 e1571908 aurel32
    else
795 e1571908 aurel32
#endif
796 e1571908 aurel32
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
797 e1571908 aurel32
                    1, crfD(ctx->opcode));
798 e1571908 aurel32
}
799 e1571908 aurel32
800 e1571908 aurel32
/* cmpl */
801 e1571908 aurel32
GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER)
802 e1571908 aurel32
{
803 e1571908 aurel32
#if defined(TARGET_PPC64)
804 e1571908 aurel32
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
805 e1571908 aurel32
        gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
806 e1571908 aurel32
                     0, crfD(ctx->opcode));
807 e1571908 aurel32
    else
808 e1571908 aurel32
#endif
809 e1571908 aurel32
        gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
810 e1571908 aurel32
                   0, crfD(ctx->opcode));
811 e1571908 aurel32
}
812 e1571908 aurel32
813 e1571908 aurel32
/* cmpli */
814 e1571908 aurel32
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
815 e1571908 aurel32
{
816 e1571908 aurel32
#if defined(TARGET_PPC64)
817 e1571908 aurel32
    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
818 e1571908 aurel32
        gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
819 e1571908 aurel32
                      0, crfD(ctx->opcode));
820 e1571908 aurel32
    else
821 e1571908 aurel32
#endif
822 e1571908 aurel32
        gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
823 e1571908 aurel32
                    0, crfD(ctx->opcode));
824 e1571908 aurel32
}
825 e1571908 aurel32
826 e1571908 aurel32
/* isel (PowerPC 2.03 specification) */
827 e1571908 aurel32
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
828 e1571908 aurel32
{
829 e1571908 aurel32
    int l1, l2;
830 e1571908 aurel32
    uint32_t bi = rC(ctx->opcode);
831 e1571908 aurel32
    uint32_t mask;
832 a7812ae4 pbrook
    TCGv_i32 t0;
833 e1571908 aurel32
834 e1571908 aurel32
    l1 = gen_new_label();
835 e1571908 aurel32
    l2 = gen_new_label();
836 e1571908 aurel32
837 e1571908 aurel32
    mask = 1 << (3 - (bi & 0x03));
838 a7812ae4 pbrook
    t0 = tcg_temp_new_i32();
839 fea0c503 aurel32
    tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
840 fea0c503 aurel32
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
841 e1571908 aurel32
    if (rA(ctx->opcode) == 0)
842 e1571908 aurel32
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
843 e1571908 aurel32
    else
844 e1571908 aurel32
        tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
845 e1571908 aurel32
    tcg_gen_br(l2);
846 e1571908 aurel32
    gen_set_label(l1);
847 e1571908 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
848 e1571908 aurel32
    gen_set_label(l2);
849 a7812ae4 pbrook
    tcg_temp_free_i32(t0);
850 e1571908 aurel32
}
851 e1571908 aurel32
852 79aceca5 bellard
/***                           Integer arithmetic                          ***/
853 79aceca5 bellard
854 74637406 aurel32
static always_inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, TCGv arg1, TCGv arg2, int sub)
855 74637406 aurel32
{
856 74637406 aurel32
    int l1;
857 74637406 aurel32
    TCGv t0;
858 79aceca5 bellard
859 74637406 aurel32
    l1 = gen_new_label();
860 74637406 aurel32
    /* Start with XER OV disabled, the most likely case */
861 74637406 aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
862 a7812ae4 pbrook
    t0 = tcg_temp_local_new();
863 74637406 aurel32
    tcg_gen_xor_tl(t0, arg0, arg1);
864 74637406 aurel32
#if defined(TARGET_PPC64)
865 74637406 aurel32
    if (!ctx->sf_mode)
866 74637406 aurel32
        tcg_gen_ext32s_tl(t0, t0);
867 74637406 aurel32
#endif
868 74637406 aurel32
    if (sub)
869 74637406 aurel32
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
870 74637406 aurel32
    else
871 74637406 aurel32
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
872 74637406 aurel32
    tcg_gen_xor_tl(t0, arg1, arg2);
873 74637406 aurel32
#if defined(TARGET_PPC64)
874 74637406 aurel32
    if (!ctx->sf_mode)
875 74637406 aurel32
        tcg_gen_ext32s_tl(t0, t0);
876 74637406 aurel32
#endif
877 74637406 aurel32
    if (sub)
878 74637406 aurel32
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
879 74637406 aurel32
    else
880 74637406 aurel32
        tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
881 74637406 aurel32
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
882 74637406 aurel32
    gen_set_label(l1);
883 74637406 aurel32
    tcg_temp_free(t0);
884 79aceca5 bellard
}
885 79aceca5 bellard
886 74637406 aurel32
static always_inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, TCGv arg2, int sub)
887 74637406 aurel32
{
888 74637406 aurel32
    int l1 = gen_new_label();
889 d9bce9d9 j_mayer
890 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
891 74637406 aurel32
    if (!(ctx->sf_mode)) {
892 74637406 aurel32
        TCGv t0, t1;
893 a7812ae4 pbrook
        t0 = tcg_temp_new();
894 a7812ae4 pbrook
        t1 = tcg_temp_new();
895 d9bce9d9 j_mayer
896 74637406 aurel32
        tcg_gen_ext32u_tl(t0, arg1);
897 74637406 aurel32
        tcg_gen_ext32u_tl(t1, arg2);
898 74637406 aurel32
        if (sub) {
899 74637406 aurel32
            tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
900 bdc4e053 aurel32
        } else {
901 74637406 aurel32
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
902 74637406 aurel32
        }
903 a9730017 aurel32
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
904 a9730017 aurel32
        gen_set_label(l1);
905 a9730017 aurel32
        tcg_temp_free(t0);
906 a9730017 aurel32
        tcg_temp_free(t1);
907 74637406 aurel32
    } else
908 74637406 aurel32
#endif
909 a9730017 aurel32
    {
910 a9730017 aurel32
        if (sub) {
911 a9730017 aurel32
            tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
912 a9730017 aurel32
        } else {
913 a9730017 aurel32
            tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
914 a9730017 aurel32
        }
915 a9730017 aurel32
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
916 a9730017 aurel32
        gen_set_label(l1);
917 74637406 aurel32
    }
918 d9bce9d9 j_mayer
}
919 d9bce9d9 j_mayer
920 74637406 aurel32
/* Common add function */
921 74637406 aurel32
static always_inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
922 74637406 aurel32
                                           int add_ca, int compute_ca, int compute_ov)
923 74637406 aurel32
{
924 74637406 aurel32
    TCGv t0, t1;
925 d9bce9d9 j_mayer
926 74637406 aurel32
    if ((!compute_ca && !compute_ov) ||
927 a7812ae4 pbrook
        (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2)))  {
928 74637406 aurel32
        t0 = ret;
929 74637406 aurel32
    } else {
930 a7812ae4 pbrook
        t0 = tcg_temp_local_new();
931 74637406 aurel32
    }
932 79aceca5 bellard
933 74637406 aurel32
    if (add_ca) {
934 a7812ae4 pbrook
        t1 = tcg_temp_local_new();
935 74637406 aurel32
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
936 74637406 aurel32
        tcg_gen_shri_tl(t1, t1, XER_CA);
937 74637406 aurel32
    }
938 79aceca5 bellard
939 74637406 aurel32
    if (compute_ca && compute_ov) {
940 74637406 aurel32
        /* Start with XER CA and OV disabled, the most likely case */
941 74637406 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
942 74637406 aurel32
    } else if (compute_ca) {
943 74637406 aurel32
        /* Start with XER CA disabled, the most likely case */
944 74637406 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
945 74637406 aurel32
    } else if (compute_ov) {
946 74637406 aurel32
        /* Start with XER OV disabled, the most likely case */
947 74637406 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
948 74637406 aurel32
    }
949 79aceca5 bellard
950 74637406 aurel32
    tcg_gen_add_tl(t0, arg1, arg2);
951 74637406 aurel32
952 74637406 aurel32
    if (compute_ca) {
953 74637406 aurel32
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
954 74637406 aurel32
    }
955 74637406 aurel32
    if (add_ca) {
956 74637406 aurel32
        tcg_gen_add_tl(t0, t0, t1);
957 74637406 aurel32
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
958 74637406 aurel32
        tcg_temp_free(t1);
959 74637406 aurel32
    }
960 74637406 aurel32
    if (compute_ov) {
961 74637406 aurel32
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
962 74637406 aurel32
    }
963 74637406 aurel32
964 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
965 74637406 aurel32
        gen_set_Rc0(ctx, t0);
966 74637406 aurel32
967 a7812ae4 pbrook
    if (!TCGV_EQUAL(t0, ret)) {
968 74637406 aurel32
        tcg_gen_mov_tl(ret, t0);
969 74637406 aurel32
        tcg_temp_free(t0);
970 74637406 aurel32
    }
971 39dd32ee aurel32
}
972 74637406 aurel32
/* Add functions with two operands */
973 74637406 aurel32
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov)         \
974 74637406 aurel32
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER)                  \
975 74637406 aurel32
{                                                                             \
976 74637406 aurel32
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
977 74637406 aurel32
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
978 74637406 aurel32
                     add_ca, compute_ca, compute_ov);                         \
979 74637406 aurel32
}
980 74637406 aurel32
/* Add functions with one operand and one immediate */
981 74637406 aurel32
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val,                        \
982 74637406 aurel32
                                add_ca, compute_ca, compute_ov)               \
983 74637406 aurel32
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER)                  \
984 74637406 aurel32
{                                                                             \
985 74637406 aurel32
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
986 74637406 aurel32
    gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)],                           \
987 74637406 aurel32
                     cpu_gpr[rA(ctx->opcode)], t0,                            \
988 74637406 aurel32
                     add_ca, compute_ca, compute_ov);                         \
989 74637406 aurel32
    tcg_temp_free(t0);                                                        \
990 74637406 aurel32
}
991 74637406 aurel32
992 74637406 aurel32
/* add  add.  addo  addo. */
993 74637406 aurel32
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
994 74637406 aurel32
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
995 74637406 aurel32
/* addc  addc.  addco  addco. */
996 74637406 aurel32
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
997 74637406 aurel32
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
998 74637406 aurel32
/* adde  adde.  addeo  addeo. */
999 74637406 aurel32
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
1000 74637406 aurel32
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
1001 74637406 aurel32
/* addme  addme.  addmeo  addmeo.  */
1002 74637406 aurel32
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
1003 74637406 aurel32
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
1004 74637406 aurel32
/* addze  addze.  addzeo  addzeo.*/
1005 74637406 aurel32
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
1006 74637406 aurel32
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
1007 74637406 aurel32
/* addi */
1008 74637406 aurel32
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1009 d9bce9d9 j_mayer
{
1010 74637406 aurel32
    target_long simm = SIMM(ctx->opcode);
1011 74637406 aurel32
1012 74637406 aurel32
    if (rA(ctx->opcode) == 0) {
1013 74637406 aurel32
        /* li case */
1014 74637406 aurel32
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
1015 74637406 aurel32
    } else {
1016 74637406 aurel32
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
1017 74637406 aurel32
    }
1018 d9bce9d9 j_mayer
}
1019 74637406 aurel32
/* addic  addic.*/
1020 74637406 aurel32
static always_inline void gen_op_addic (DisasContext *ctx, TCGv ret, TCGv arg1,
1021 74637406 aurel32
                                        int compute_Rc0)
1022 d9bce9d9 j_mayer
{
1023 74637406 aurel32
    target_long simm = SIMM(ctx->opcode);
1024 74637406 aurel32
1025 74637406 aurel32
    /* Start with XER CA and OV disabled, the most likely case */
1026 74637406 aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1027 74637406 aurel32
1028 74637406 aurel32
    if (likely(simm != 0)) {
1029 a7812ae4 pbrook
        TCGv t0 = tcg_temp_local_new();
1030 74637406 aurel32
        tcg_gen_addi_tl(t0, arg1, simm);
1031 74637406 aurel32
        gen_op_arith_compute_ca(ctx, t0, arg1, 0);
1032 74637406 aurel32
        tcg_gen_mov_tl(ret, t0);
1033 74637406 aurel32
        tcg_temp_free(t0);
1034 74637406 aurel32
    } else {
1035 74637406 aurel32
        tcg_gen_mov_tl(ret, arg1);
1036 74637406 aurel32
    }
1037 74637406 aurel32
    if (compute_Rc0) {
1038 74637406 aurel32
        gen_set_Rc0(ctx, ret);
1039 74637406 aurel32
    }
1040 d9bce9d9 j_mayer
}
1041 74637406 aurel32
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1042 d9bce9d9 j_mayer
{
1043 74637406 aurel32
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1044 d9bce9d9 j_mayer
}
1045 74637406 aurel32
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1046 d9bce9d9 j_mayer
{
1047 74637406 aurel32
    gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1048 d9bce9d9 j_mayer
}
1049 74637406 aurel32
/* addis */
1050 74637406 aurel32
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1051 d9bce9d9 j_mayer
{
1052 74637406 aurel32
    target_long simm = SIMM(ctx->opcode);
1053 74637406 aurel32
1054 74637406 aurel32
    if (rA(ctx->opcode) == 0) {
1055 74637406 aurel32
        /* lis case */
1056 74637406 aurel32
        tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
1057 74637406 aurel32
    } else {
1058 74637406 aurel32
        tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
1059 74637406 aurel32
    }
1060 d9bce9d9 j_mayer
}
1061 74637406 aurel32
1062 74637406 aurel32
static always_inline void gen_op_arith_divw (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
1063 74637406 aurel32
                                             int sign, int compute_ov)
1064 d9bce9d9 j_mayer
{
1065 2ef1b120 aurel32
    int l1 = gen_new_label();
1066 2ef1b120 aurel32
    int l2 = gen_new_label();
1067 a7812ae4 pbrook
    TCGv_i32 t0 = tcg_temp_local_new_i32();
1068 a7812ae4 pbrook
    TCGv_i32 t1 = tcg_temp_local_new_i32();
1069 74637406 aurel32
1070 2ef1b120 aurel32
    tcg_gen_trunc_tl_i32(t0, arg1);
1071 2ef1b120 aurel32
    tcg_gen_trunc_tl_i32(t1, arg2);
1072 2ef1b120 aurel32
    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
1073 74637406 aurel32
    if (sign) {
1074 2ef1b120 aurel32
        int l3 = gen_new_label();
1075 2ef1b120 aurel32
        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
1076 2ef1b120 aurel32
        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
1077 74637406 aurel32
        gen_set_label(l3);
1078 2ef1b120 aurel32
        tcg_gen_div_i32(t0, t0, t1);
1079 74637406 aurel32
    } else {
1080 2ef1b120 aurel32
        tcg_gen_divu_i32(t0, t0, t1);
1081 74637406 aurel32
    }
1082 74637406 aurel32
    if (compute_ov) {
1083 74637406 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1084 74637406 aurel32
    }
1085 74637406 aurel32
    tcg_gen_br(l2);
1086 74637406 aurel32
    gen_set_label(l1);
1087 74637406 aurel32
    if (sign) {
1088 2ef1b120 aurel32
        tcg_gen_sari_i32(t0, t0, 31);
1089 74637406 aurel32
    } else {
1090 74637406 aurel32
        tcg_gen_movi_i32(t0, 0);
1091 74637406 aurel32
    }
1092 74637406 aurel32
    if (compute_ov) {
1093 74637406 aurel32
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1094 74637406 aurel32
    }
1095 74637406 aurel32
    gen_set_label(l2);
1096 2ef1b120 aurel32
    tcg_gen_extu_i32_tl(ret, t0);
1097 a7812ae4 pbrook
    tcg_temp_free_i32(t0);
1098 a7812ae4 pbrook
    tcg_temp_free_i32(t1);
1099 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1100 74637406 aurel32
        gen_set_Rc0(ctx, ret);
1101 d9bce9d9 j_mayer
}
1102 74637406 aurel32
/* Div functions */
1103 74637406 aurel32
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov)                      \
1104 74637406 aurel32
GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)                  \
1105 74637406 aurel32
{                                                                             \
1106 74637406 aurel32
    gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1107 74637406 aurel32
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],      \
1108 74637406 aurel32
                     sign, compute_ov);                                       \
1109 74637406 aurel32
}
1110 74637406 aurel32
/* divwu  divwu.  divwuo  divwuo.   */
1111 74637406 aurel32
GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
1112 74637406 aurel32
GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
1113 74637406 aurel32
/* divw  divw.  divwo  divwo.   */
1114 74637406 aurel32
GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
1115 74637406 aurel32
GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
1116 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1117 2ef1b120 aurel32
static always_inline void gen_op_arith_divd (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
1118 2ef1b120 aurel32
                                             int sign, int compute_ov)
1119 d9bce9d9 j_mayer
{
1120 2ef1b120 aurel32
    int l1 = gen_new_label();
1121 2ef1b120 aurel32
    int l2 = gen_new_label();
1122 74637406 aurel32
1123 74637406 aurel32
    tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
1124 74637406 aurel32
    if (sign) {
1125 2ef1b120 aurel32
        int l3 = gen_new_label();
1126 74637406 aurel32
        tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
1127 74637406 aurel32
        tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
1128 74637406 aurel32
        gen_set_label(l3);
1129 74637406 aurel32
        tcg_gen_div_i64(ret, arg1, arg2);
1130 74637406 aurel32
    } else {
1131 74637406 aurel32
        tcg_gen_divu_i64(ret, arg1, arg2);
1132 74637406 aurel32
    }
1133 74637406 aurel32
    if (compute_ov) {
1134 74637406 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1135 74637406 aurel32
    }
1136 74637406 aurel32
    tcg_gen_br(l2);
1137 74637406 aurel32
    gen_set_label(l1);
1138 74637406 aurel32
    if (sign) {
1139 74637406 aurel32
        tcg_gen_sari_i64(ret, arg1, 63);
1140 74637406 aurel32
    } else {
1141 74637406 aurel32
        tcg_gen_movi_i64(ret, 0);
1142 74637406 aurel32
    }
1143 74637406 aurel32
    if (compute_ov) {
1144 74637406 aurel32
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1145 74637406 aurel32
    }
1146 74637406 aurel32
    gen_set_label(l2);
1147 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1148 74637406 aurel32
        gen_set_Rc0(ctx, ret);
1149 d9bce9d9 j_mayer
}
1150 74637406 aurel32
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov)                      \
1151 74637406 aurel32
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)                      \
1152 74637406 aurel32
{                                                                             \
1153 2ef1b120 aurel32
    gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1154 2ef1b120 aurel32
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1155 2ef1b120 aurel32
                      sign, compute_ov);                                      \
1156 74637406 aurel32
}
1157 74637406 aurel32
/* divwu  divwu.  divwuo  divwuo.   */
1158 74637406 aurel32
GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1159 74637406 aurel32
GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1160 74637406 aurel32
/* divw  divw.  divwo  divwo.   */
1161 74637406 aurel32
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1162 74637406 aurel32
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
1163 d9bce9d9 j_mayer
#endif
1164 74637406 aurel32
1165 74637406 aurel32
/* mulhw  mulhw. */
1166 74637406 aurel32
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER)
1167 d9bce9d9 j_mayer
{
1168 a7812ae4 pbrook
    TCGv_i64 t0, t1;
1169 74637406 aurel32
1170 a7812ae4 pbrook
    t0 = tcg_temp_new_i64();
1171 a7812ae4 pbrook
    t1 = tcg_temp_new_i64();
1172 74637406 aurel32
#if defined(TARGET_PPC64)
1173 74637406 aurel32
    tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1174 74637406 aurel32
    tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1175 74637406 aurel32
    tcg_gen_mul_i64(t0, t0, t1);
1176 74637406 aurel32
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1177 74637406 aurel32
#else
1178 74637406 aurel32
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1179 74637406 aurel32
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1180 74637406 aurel32
    tcg_gen_mul_i64(t0, t0, t1);
1181 74637406 aurel32
    tcg_gen_shri_i64(t0, t0, 32);
1182 74637406 aurel32
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1183 74637406 aurel32
#endif
1184 a7812ae4 pbrook
    tcg_temp_free_i64(t0);
1185 a7812ae4 pbrook
    tcg_temp_free_i64(t1);
1186 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1187 74637406 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1188 d9bce9d9 j_mayer
}
1189 74637406 aurel32
/* mulhwu  mulhwu.  */
1190 74637406 aurel32
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER)
1191 d9bce9d9 j_mayer
{
1192 a7812ae4 pbrook
    TCGv_i64 t0, t1;
1193 74637406 aurel32
1194 a7812ae4 pbrook
    t0 = tcg_temp_new_i64();
1195 a7812ae4 pbrook
    t1 = tcg_temp_new_i64();
1196 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1197 74637406 aurel32
    tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1198 74637406 aurel32
    tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1199 74637406 aurel32
    tcg_gen_mul_i64(t0, t0, t1);
1200 74637406 aurel32
    tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1201 74637406 aurel32
#else
1202 74637406 aurel32
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1203 74637406 aurel32
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1204 74637406 aurel32
    tcg_gen_mul_i64(t0, t0, t1);
1205 74637406 aurel32
    tcg_gen_shri_i64(t0, t0, 32);
1206 74637406 aurel32
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1207 74637406 aurel32
#endif
1208 a7812ae4 pbrook
    tcg_temp_free_i64(t0);
1209 a7812ae4 pbrook
    tcg_temp_free_i64(t1);
1210 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1211 74637406 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1212 d9bce9d9 j_mayer
}
1213 74637406 aurel32
/* mullw  mullw. */
1214 74637406 aurel32
GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER)
1215 d9bce9d9 j_mayer
{
1216 74637406 aurel32
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1217 74637406 aurel32
                   cpu_gpr[rB(ctx->opcode)]);
1218 1e4c090f aurel32
    tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
1219 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1220 74637406 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1221 d9bce9d9 j_mayer
}
1222 74637406 aurel32
/* mullwo  mullwo. */
1223 74637406 aurel32
GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER)
1224 d9bce9d9 j_mayer
{
1225 74637406 aurel32
    int l1;
1226 a7812ae4 pbrook
    TCGv_i64 t0, t1;
1227 74637406 aurel32
1228 a7812ae4 pbrook
    t0 = tcg_temp_new_i64();
1229 a7812ae4 pbrook
    t1 = tcg_temp_new_i64();
1230 74637406 aurel32
    l1 = gen_new_label();
1231 74637406 aurel32
    /* Start with XER OV disabled, the most likely case */
1232 74637406 aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1233 74637406 aurel32
#if defined(TARGET_PPC64)
1234 74637406 aurel32
    tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1235 74637406 aurel32
    tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1236 74637406 aurel32
#else
1237 74637406 aurel32
    tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1238 74637406 aurel32
    tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1239 d9bce9d9 j_mayer
#endif
1240 74637406 aurel32
    tcg_gen_mul_i64(t0, t0, t1);
1241 74637406 aurel32
#if defined(TARGET_PPC64)
1242 74637406 aurel32
    tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
1243 74637406 aurel32
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
1244 74637406 aurel32
#else
1245 74637406 aurel32
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1246 74637406 aurel32
    tcg_gen_ext32s_i64(t1, t0);
1247 74637406 aurel32
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
1248 74637406 aurel32
#endif
1249 74637406 aurel32
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1250 74637406 aurel32
    gen_set_label(l1);
1251 a7812ae4 pbrook
    tcg_temp_free_i64(t0);
1252 a7812ae4 pbrook
    tcg_temp_free_i64(t1);
1253 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1254 74637406 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1255 d9bce9d9 j_mayer
}
1256 74637406 aurel32
/* mulli */
1257 74637406 aurel32
GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1258 d9bce9d9 j_mayer
{
1259 74637406 aurel32
    tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1260 74637406 aurel32
                    SIMM(ctx->opcode));
1261 d9bce9d9 j_mayer
}
1262 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1263 74637406 aurel32
#define GEN_INT_ARITH_MUL_HELPER(name, opc3)                                  \
1264 74637406 aurel32
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)                      \
1265 74637406 aurel32
{                                                                             \
1266 a7812ae4 pbrook
    gen_helper_##name (cpu_gpr[rD(ctx->opcode)],                              \
1267 74637406 aurel32
                       cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);   \
1268 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1269 74637406 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);                           \
1270 d9bce9d9 j_mayer
}
1271 74637406 aurel32
/* mulhd  mulhd. */
1272 74637406 aurel32
GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
1273 74637406 aurel32
/* mulhdu  mulhdu. */
1274 74637406 aurel32
GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
1275 74637406 aurel32
/* mulld  mulld. */
1276 74637406 aurel32
GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B)
1277 d9bce9d9 j_mayer
{
1278 74637406 aurel32
    tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1279 74637406 aurel32
                   cpu_gpr[rB(ctx->opcode)]);
1280 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1281 74637406 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1282 d9bce9d9 j_mayer
}
1283 74637406 aurel32
/* mulldo  mulldo. */
1284 74637406 aurel32
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
1285 d9bce9d9 j_mayer
#endif
1286 74637406 aurel32
1287 74637406 aurel32
/* neg neg. nego nego. */
1288 ec6469a3 aurel32
static always_inline void gen_op_arith_neg (DisasContext *ctx, TCGv ret, TCGv arg1, int ov_check)
1289 d9bce9d9 j_mayer
{
1290 ec6469a3 aurel32
    int l1 = gen_new_label();
1291 ec6469a3 aurel32
    int l2 = gen_new_label();
1292 a7812ae4 pbrook
    TCGv t0 = tcg_temp_local_new();
1293 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1294 74637406 aurel32
    if (ctx->sf_mode) {
1295 741a7444 aurel32
        tcg_gen_mov_tl(t0, arg1);
1296 ec6469a3 aurel32
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
1297 ec6469a3 aurel32
    } else
1298 ec6469a3 aurel32
#endif
1299 ec6469a3 aurel32
    {
1300 ec6469a3 aurel32
        tcg_gen_ext32s_tl(t0, arg1);
1301 74637406 aurel32
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
1302 74637406 aurel32
    }
1303 74637406 aurel32
    tcg_gen_neg_tl(ret, arg1);
1304 74637406 aurel32
    if (ov_check) {
1305 74637406 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1306 74637406 aurel32
    }
1307 74637406 aurel32
    tcg_gen_br(l2);
1308 74637406 aurel32
    gen_set_label(l1);
1309 ec6469a3 aurel32
    tcg_gen_mov_tl(ret, t0);
1310 74637406 aurel32
    if (ov_check) {
1311 74637406 aurel32
        tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1312 74637406 aurel32
    }
1313 74637406 aurel32
    gen_set_label(l2);
1314 ec6469a3 aurel32
    tcg_temp_free(t0);
1315 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1316 74637406 aurel32
        gen_set_Rc0(ctx, ret);
1317 74637406 aurel32
}
1318 74637406 aurel32
GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER)
1319 d9bce9d9 j_mayer
{
1320 ec6469a3 aurel32
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
1321 d9bce9d9 j_mayer
}
1322 74637406 aurel32
GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER)
1323 79aceca5 bellard
{
1324 ec6469a3 aurel32
    gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
1325 79aceca5 bellard
}
1326 74637406 aurel32
1327 74637406 aurel32
/* Common subf function */
1328 74637406 aurel32
static always_inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
1329 74637406 aurel32
                                            int add_ca, int compute_ca, int compute_ov)
1330 79aceca5 bellard
{
1331 74637406 aurel32
    TCGv t0, t1;
1332 76a66253 j_mayer
1333 74637406 aurel32
    if ((!compute_ca && !compute_ov) ||
1334 a7812ae4 pbrook
        (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2)))  {
1335 74637406 aurel32
        t0 = ret;
1336 e864cabd j_mayer
    } else {
1337 a7812ae4 pbrook
        t0 = tcg_temp_local_new();
1338 d9bce9d9 j_mayer
    }
1339 76a66253 j_mayer
1340 74637406 aurel32
    if (add_ca) {
1341 a7812ae4 pbrook
        t1 = tcg_temp_local_new();
1342 74637406 aurel32
        tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
1343 74637406 aurel32
        tcg_gen_shri_tl(t1, t1, XER_CA);
1344 d9bce9d9 j_mayer
    }
1345 79aceca5 bellard
1346 74637406 aurel32
    if (compute_ca && compute_ov) {
1347 74637406 aurel32
        /* Start with XER CA and OV disabled, the most likely case */
1348 74637406 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
1349 74637406 aurel32
    } else if (compute_ca) {
1350 74637406 aurel32
        /* Start with XER CA disabled, the most likely case */
1351 74637406 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1352 74637406 aurel32
    } else if (compute_ov) {
1353 74637406 aurel32
        /* Start with XER OV disabled, the most likely case */
1354 74637406 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1355 74637406 aurel32
    }
1356 74637406 aurel32
1357 74637406 aurel32
    if (add_ca) {
1358 74637406 aurel32
        tcg_gen_not_tl(t0, arg1);
1359 74637406 aurel32
        tcg_gen_add_tl(t0, t0, arg2);
1360 74637406 aurel32
        gen_op_arith_compute_ca(ctx, t0, arg2, 0);
1361 74637406 aurel32
        tcg_gen_add_tl(t0, t0, t1);
1362 74637406 aurel32
        gen_op_arith_compute_ca(ctx, t0, t1, 0);
1363 74637406 aurel32
        tcg_temp_free(t1);
1364 79aceca5 bellard
    } else {
1365 74637406 aurel32
        tcg_gen_sub_tl(t0, arg2, arg1);
1366 74637406 aurel32
        if (compute_ca) {
1367 74637406 aurel32
            gen_op_arith_compute_ca(ctx, t0, arg2, 1);
1368 74637406 aurel32
        }
1369 74637406 aurel32
    }
1370 74637406 aurel32
    if (compute_ov) {
1371 74637406 aurel32
        gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1372 74637406 aurel32
    }
1373 74637406 aurel32
1374 74637406 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1375 74637406 aurel32
        gen_set_Rc0(ctx, t0);
1376 74637406 aurel32
1377 a7812ae4 pbrook
    if (!TCGV_EQUAL(t0, ret)) {
1378 74637406 aurel32
        tcg_gen_mov_tl(ret, t0);
1379 74637406 aurel32
        tcg_temp_free(t0);
1380 79aceca5 bellard
    }
1381 79aceca5 bellard
}
1382 74637406 aurel32
/* Sub functions with Two operands functions */
1383 74637406 aurel32
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov)        \
1384 74637406 aurel32
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER)                  \
1385 74637406 aurel32
{                                                                             \
1386 74637406 aurel32
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1387 74637406 aurel32
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],     \
1388 74637406 aurel32
                      add_ca, compute_ca, compute_ov);                        \
1389 74637406 aurel32
}
1390 74637406 aurel32
/* Sub functions with one operand and one immediate */
1391 74637406 aurel32
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val,                       \
1392 74637406 aurel32
                                add_ca, compute_ca, compute_ov)               \
1393 74637406 aurel32
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER)                  \
1394 74637406 aurel32
{                                                                             \
1395 74637406 aurel32
    TCGv t0 = tcg_const_local_tl(const_val);                                  \
1396 74637406 aurel32
    gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)],                          \
1397 74637406 aurel32
                      cpu_gpr[rA(ctx->opcode)], t0,                           \
1398 74637406 aurel32
                      add_ca, compute_ca, compute_ov);                        \
1399 74637406 aurel32
    tcg_temp_free(t0);                                                        \
1400 74637406 aurel32
}
1401 74637406 aurel32
/* subf  subf.  subfo  subfo. */
1402 74637406 aurel32
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1403 74637406 aurel32
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1404 74637406 aurel32
/* subfc  subfc.  subfco  subfco. */
1405 74637406 aurel32
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1406 74637406 aurel32
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1407 74637406 aurel32
/* subfe  subfe.  subfeo  subfo. */
1408 74637406 aurel32
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1409 74637406 aurel32
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1410 74637406 aurel32
/* subfme  subfme.  subfmeo  subfmeo.  */
1411 74637406 aurel32
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1412 74637406 aurel32
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1413 74637406 aurel32
/* subfze  subfze.  subfzeo  subfzeo.*/
1414 74637406 aurel32
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1415 74637406 aurel32
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
1416 79aceca5 bellard
/* subfic */
1417 79aceca5 bellard
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1418 79aceca5 bellard
{
1419 74637406 aurel32
    /* Start with XER CA and OV disabled, the most likely case */
1420 74637406 aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1421 a7812ae4 pbrook
    TCGv t0 = tcg_temp_local_new();
1422 74637406 aurel32
    TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
1423 74637406 aurel32
    tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
1424 74637406 aurel32
    gen_op_arith_compute_ca(ctx, t0, t1, 1);
1425 74637406 aurel32
    tcg_temp_free(t1);
1426 74637406 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
1427 74637406 aurel32
    tcg_temp_free(t0);
1428 79aceca5 bellard
}
1429 79aceca5 bellard
1430 79aceca5 bellard
/***                            Integer logical                            ***/
1431 26d67362 aurel32
#define GEN_LOGICAL2(name, tcg_op, opc, type)                                 \
1432 26d67362 aurel32
GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)                          \
1433 79aceca5 bellard
{                                                                             \
1434 26d67362 aurel32
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],                \
1435 26d67362 aurel32
       cpu_gpr[rB(ctx->opcode)]);                                             \
1436 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1437 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1438 79aceca5 bellard
}
1439 79aceca5 bellard
1440 26d67362 aurel32
#define GEN_LOGICAL1(name, tcg_op, opc, type)                                 \
1441 d9bce9d9 j_mayer
GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)                          \
1442 79aceca5 bellard
{                                                                             \
1443 26d67362 aurel32
    tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);               \
1444 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))                                       \
1445 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);                           \
1446 79aceca5 bellard
}
1447 79aceca5 bellard
1448 79aceca5 bellard
/* and & and. */
1449 26d67362 aurel32
GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
1450 79aceca5 bellard
/* andc & andc. */
1451 26d67362 aurel32
GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
1452 79aceca5 bellard
/* andi. */
1453 c7697e1f j_mayer
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1454 79aceca5 bellard
{
1455 26d67362 aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1456 26d67362 aurel32
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1457 79aceca5 bellard
}
1458 79aceca5 bellard
/* andis. */
1459 c7697e1f j_mayer
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1460 79aceca5 bellard
{
1461 26d67362 aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1462 26d67362 aurel32
    gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1463 79aceca5 bellard
}
1464 79aceca5 bellard
/* cntlzw */
1465 26d67362 aurel32
GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER)
1466 26d67362 aurel32
{
1467 a7812ae4 pbrook
    gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1468 26d67362 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1469 2e31f5d3 pbrook
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1470 26d67362 aurel32
}
1471 79aceca5 bellard
/* eqv & eqv. */
1472 26d67362 aurel32
GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
1473 79aceca5 bellard
/* extsb & extsb. */
1474 26d67362 aurel32
GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
1475 79aceca5 bellard
/* extsh & extsh. */
1476 26d67362 aurel32
GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
1477 79aceca5 bellard
/* nand & nand. */
1478 26d67362 aurel32
GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
1479 79aceca5 bellard
/* nor & nor. */
1480 26d67362 aurel32
GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
1481 79aceca5 bellard
/* or & or. */
1482 9a64fbe4 bellard
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
1483 9a64fbe4 bellard
{
1484 76a66253 j_mayer
    int rs, ra, rb;
1485 76a66253 j_mayer
1486 76a66253 j_mayer
    rs = rS(ctx->opcode);
1487 76a66253 j_mayer
    ra = rA(ctx->opcode);
1488 76a66253 j_mayer
    rb = rB(ctx->opcode);
1489 76a66253 j_mayer
    /* Optimisation for mr. ri case */
1490 76a66253 j_mayer
    if (rs != ra || rs != rb) {
1491 26d67362 aurel32
        if (rs != rb)
1492 26d67362 aurel32
            tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1493 26d67362 aurel32
        else
1494 26d67362 aurel32
            tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
1495 76a66253 j_mayer
        if (unlikely(Rc(ctx->opcode) != 0))
1496 26d67362 aurel32
            gen_set_Rc0(ctx, cpu_gpr[ra]);
1497 76a66253 j_mayer
    } else if (unlikely(Rc(ctx->opcode) != 0)) {
1498 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rs]);
1499 c80f84e3 j_mayer
#if defined(TARGET_PPC64)
1500 c80f84e3 j_mayer
    } else {
1501 26d67362 aurel32
        int prio = 0;
1502 26d67362 aurel32
1503 c80f84e3 j_mayer
        switch (rs) {
1504 c80f84e3 j_mayer
        case 1:
1505 c80f84e3 j_mayer
            /* Set process priority to low */
1506 26d67362 aurel32
            prio = 2;
1507 c80f84e3 j_mayer
            break;
1508 c80f84e3 j_mayer
        case 6:
1509 c80f84e3 j_mayer
            /* Set process priority to medium-low */
1510 26d67362 aurel32
            prio = 3;
1511 c80f84e3 j_mayer
            break;
1512 c80f84e3 j_mayer
        case 2:
1513 c80f84e3 j_mayer
            /* Set process priority to normal */
1514 26d67362 aurel32
            prio = 4;
1515 c80f84e3 j_mayer
            break;
1516 be147d08 j_mayer
#if !defined(CONFIG_USER_ONLY)
1517 be147d08 j_mayer
        case 31:
1518 76db3ba4 aurel32
            if (ctx->mem_idx > 0) {
1519 be147d08 j_mayer
                /* Set process priority to very low */
1520 26d67362 aurel32
                prio = 1;
1521 be147d08 j_mayer
            }
1522 be147d08 j_mayer
            break;
1523 be147d08 j_mayer
        case 5:
1524 76db3ba4 aurel32
            if (ctx->mem_idx > 0) {
1525 be147d08 j_mayer
                /* Set process priority to medium-hight */
1526 26d67362 aurel32
                prio = 5;
1527 be147d08 j_mayer
            }
1528 be147d08 j_mayer
            break;
1529 be147d08 j_mayer
        case 3:
1530 76db3ba4 aurel32
            if (ctx->mem_idx > 0) {
1531 be147d08 j_mayer
                /* Set process priority to high */
1532 26d67362 aurel32
                prio = 6;
1533 be147d08 j_mayer
            }
1534 be147d08 j_mayer
            break;
1535 be147d08 j_mayer
        case 7:
1536 76db3ba4 aurel32
            if (ctx->mem_idx > 1) {
1537 be147d08 j_mayer
                /* Set process priority to very high */
1538 26d67362 aurel32
                prio = 7;
1539 be147d08 j_mayer
            }
1540 be147d08 j_mayer
            break;
1541 be147d08 j_mayer
#endif
1542 c80f84e3 j_mayer
        default:
1543 c80f84e3 j_mayer
            /* nop */
1544 c80f84e3 j_mayer
            break;
1545 c80f84e3 j_mayer
        }
1546 26d67362 aurel32
        if (prio) {
1547 a7812ae4 pbrook
            TCGv t0 = tcg_temp_new();
1548 54cdcae6 aurel32
            gen_load_spr(t0, SPR_PPR);
1549 ea363694 aurel32
            tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1550 ea363694 aurel32
            tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1551 54cdcae6 aurel32
            gen_store_spr(SPR_PPR, t0);
1552 ea363694 aurel32
            tcg_temp_free(t0);
1553 26d67362 aurel32
        }
1554 c80f84e3 j_mayer
#endif
1555 9a64fbe4 bellard
    }
1556 9a64fbe4 bellard
}
1557 79aceca5 bellard
/* orc & orc. */
1558 26d67362 aurel32
GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
1559 79aceca5 bellard
/* xor & xor. */
1560 9a64fbe4 bellard
GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
1561 9a64fbe4 bellard
{
1562 9a64fbe4 bellard
    /* Optimisation for "set to zero" case */
1563 26d67362 aurel32
    if (rS(ctx->opcode) != rB(ctx->opcode))
1564 312179c4 aurel32
        tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1565 26d67362 aurel32
    else
1566 26d67362 aurel32
        tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1567 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
1568 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1569 9a64fbe4 bellard
}
1570 79aceca5 bellard
/* ori */
1571 79aceca5 bellard
GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1572 79aceca5 bellard
{
1573 76a66253 j_mayer
    target_ulong uimm = UIMM(ctx->opcode);
1574 79aceca5 bellard
1575 9a64fbe4 bellard
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1576 9a64fbe4 bellard
        /* NOP */
1577 76a66253 j_mayer
        /* XXX: should handle special NOPs for POWER series */
1578 9a64fbe4 bellard
        return;
1579 76a66253 j_mayer
    }
1580 26d67362 aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1581 79aceca5 bellard
}
1582 79aceca5 bellard
/* oris */
1583 79aceca5 bellard
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1584 79aceca5 bellard
{
1585 76a66253 j_mayer
    target_ulong uimm = UIMM(ctx->opcode);
1586 79aceca5 bellard
1587 9a64fbe4 bellard
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1588 9a64fbe4 bellard
        /* NOP */
1589 9a64fbe4 bellard
        return;
1590 76a66253 j_mayer
    }
1591 26d67362 aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1592 79aceca5 bellard
}
1593 79aceca5 bellard
/* xori */
1594 79aceca5 bellard
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1595 79aceca5 bellard
{
1596 76a66253 j_mayer
    target_ulong uimm = UIMM(ctx->opcode);
1597 9a64fbe4 bellard
1598 9a64fbe4 bellard
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1599 9a64fbe4 bellard
        /* NOP */
1600 9a64fbe4 bellard
        return;
1601 9a64fbe4 bellard
    }
1602 26d67362 aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
1603 79aceca5 bellard
}
1604 79aceca5 bellard
/* xoris */
1605 79aceca5 bellard
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1606 79aceca5 bellard
{
1607 76a66253 j_mayer
    target_ulong uimm = UIMM(ctx->opcode);
1608 9a64fbe4 bellard
1609 9a64fbe4 bellard
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1610 9a64fbe4 bellard
        /* NOP */
1611 9a64fbe4 bellard
        return;
1612 9a64fbe4 bellard
    }
1613 26d67362 aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
1614 79aceca5 bellard
}
1615 d9bce9d9 j_mayer
/* popcntb : PowerPC 2.03 specification */
1616 05332d70 j_mayer
GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB)
1617 d9bce9d9 j_mayer
{
1618 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1619 d9bce9d9 j_mayer
    if (ctx->sf_mode)
1620 a7812ae4 pbrook
        gen_helper_popcntb_64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1621 d9bce9d9 j_mayer
    else
1622 d9bce9d9 j_mayer
#endif
1623 a7812ae4 pbrook
        gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1624 d9bce9d9 j_mayer
}
1625 d9bce9d9 j_mayer
1626 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1627 d9bce9d9 j_mayer
/* extsw & extsw. */
1628 26d67362 aurel32
GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
1629 d9bce9d9 j_mayer
/* cntlzd */
1630 26d67362 aurel32
GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B)
1631 26d67362 aurel32
{
1632 a7812ae4 pbrook
    gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1633 26d67362 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1634 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1635 26d67362 aurel32
}
1636 d9bce9d9 j_mayer
#endif
1637 d9bce9d9 j_mayer
1638 79aceca5 bellard
/***                             Integer rotate                            ***/
1639 79aceca5 bellard
/* rlwimi & rlwimi. */
1640 79aceca5 bellard
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1641 79aceca5 bellard
{
1642 76a66253 j_mayer
    uint32_t mb, me, sh;
1643 79aceca5 bellard
1644 79aceca5 bellard
    mb = MB(ctx->opcode);
1645 79aceca5 bellard
    me = ME(ctx->opcode);
1646 76a66253 j_mayer
    sh = SH(ctx->opcode);
1647 d03ef511 aurel32
    if (likely(sh == 0 && mb == 0 && me == 31)) {
1648 d03ef511 aurel32
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1649 d03ef511 aurel32
    } else {
1650 d03ef511 aurel32
        target_ulong mask;
1651 a7812ae4 pbrook
        TCGv t1;
1652 a7812ae4 pbrook
        TCGv t0 = tcg_temp_new();
1653 54843a58 aurel32
#if defined(TARGET_PPC64)
1654 a7812ae4 pbrook
        TCGv_i32 t2 = tcg_temp_new_i32();
1655 a7812ae4 pbrook
        tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
1656 a7812ae4 pbrook
        tcg_gen_rotli_i32(t2, t2, sh);
1657 a7812ae4 pbrook
        tcg_gen_extu_i32_i64(t0, t2);
1658 a7812ae4 pbrook
        tcg_temp_free_i32(t2);
1659 54843a58 aurel32
#else
1660 54843a58 aurel32
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1661 54843a58 aurel32
#endif
1662 76a66253 j_mayer
#if defined(TARGET_PPC64)
1663 d03ef511 aurel32
        mb += 32;
1664 d03ef511 aurel32
        me += 32;
1665 76a66253 j_mayer
#endif
1666 d03ef511 aurel32
        mask = MASK(mb, me);
1667 a7812ae4 pbrook
        t1 = tcg_temp_new();
1668 d03ef511 aurel32
        tcg_gen_andi_tl(t0, t0, mask);
1669 d03ef511 aurel32
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1670 d03ef511 aurel32
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1671 d03ef511 aurel32
        tcg_temp_free(t0);
1672 d03ef511 aurel32
        tcg_temp_free(t1);
1673 d03ef511 aurel32
    }
1674 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
1675 d03ef511 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1676 79aceca5 bellard
}
1677 79aceca5 bellard
/* rlwinm & rlwinm. */
1678 79aceca5 bellard
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1679 79aceca5 bellard
{
1680 79aceca5 bellard
    uint32_t mb, me, sh;
1681 3b46e624 ths
1682 79aceca5 bellard
    sh = SH(ctx->opcode);
1683 79aceca5 bellard
    mb = MB(ctx->opcode);
1684 79aceca5 bellard
    me = ME(ctx->opcode);
1685 d03ef511 aurel32
1686 d03ef511 aurel32
    if (likely(mb == 0 && me == (31 - sh))) {
1687 d03ef511 aurel32
        if (likely(sh == 0)) {
1688 d03ef511 aurel32
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1689 d03ef511 aurel32
        } else {
1690 a7812ae4 pbrook
            TCGv t0 = tcg_temp_new();
1691 d03ef511 aurel32
            tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1692 d03ef511 aurel32
            tcg_gen_shli_tl(t0, t0, sh);
1693 d03ef511 aurel32
            tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1694 d03ef511 aurel32
            tcg_temp_free(t0);
1695 79aceca5 bellard
        }
1696 d03ef511 aurel32
    } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
1697 a7812ae4 pbrook
        TCGv t0 = tcg_temp_new();
1698 d03ef511 aurel32
        tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1699 d03ef511 aurel32
        tcg_gen_shri_tl(t0, t0, mb);
1700 d03ef511 aurel32
        tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1701 d03ef511 aurel32
        tcg_temp_free(t0);
1702 d03ef511 aurel32
    } else {
1703 a7812ae4 pbrook
        TCGv t0 = tcg_temp_new();
1704 54843a58 aurel32
#if defined(TARGET_PPC64)
1705 a7812ae4 pbrook
        TCGv_i32 t1 = tcg_temp_new_i32();
1706 54843a58 aurel32
        tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1707 54843a58 aurel32
        tcg_gen_rotli_i32(t1, t1, sh);
1708 54843a58 aurel32
        tcg_gen_extu_i32_i64(t0, t1);
1709 a7812ae4 pbrook
        tcg_temp_free_i32(t1);
1710 54843a58 aurel32
#else
1711 54843a58 aurel32
        tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1712 54843a58 aurel32
#endif
1713 76a66253 j_mayer
#if defined(TARGET_PPC64)
1714 d03ef511 aurel32
        mb += 32;
1715 d03ef511 aurel32
        me += 32;
1716 76a66253 j_mayer
#endif
1717 d03ef511 aurel32
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1718 d03ef511 aurel32
        tcg_temp_free(t0);
1719 d03ef511 aurel32
    }
1720 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
1721 d03ef511 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1722 79aceca5 bellard
}
1723 79aceca5 bellard
/* rlwnm & rlwnm. */
1724 79aceca5 bellard
GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1725 79aceca5 bellard
{
1726 79aceca5 bellard
    uint32_t mb, me;
1727 54843a58 aurel32
    TCGv t0;
1728 54843a58 aurel32
#if defined(TARGET_PPC64)
1729 a7812ae4 pbrook
    TCGv_i32 t1, t2;
1730 54843a58 aurel32
#endif
1731 79aceca5 bellard
1732 79aceca5 bellard
    mb = MB(ctx->opcode);
1733 79aceca5 bellard
    me = ME(ctx->opcode);
1734 a7812ae4 pbrook
    t0 = tcg_temp_new();
1735 d03ef511 aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
1736 54843a58 aurel32
#if defined(TARGET_PPC64)
1737 a7812ae4 pbrook
    t1 = tcg_temp_new_i32();
1738 a7812ae4 pbrook
    t2 = tcg_temp_new_i32();
1739 54843a58 aurel32
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1740 54843a58 aurel32
    tcg_gen_trunc_i64_i32(t2, t0);
1741 54843a58 aurel32
    tcg_gen_rotl_i32(t1, t1, t2);
1742 54843a58 aurel32
    tcg_gen_extu_i32_i64(t0, t1);
1743 a7812ae4 pbrook
    tcg_temp_free_i32(t1);
1744 a7812ae4 pbrook
    tcg_temp_free_i32(t2);
1745 54843a58 aurel32
#else
1746 54843a58 aurel32
    tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
1747 54843a58 aurel32
#endif
1748 76a66253 j_mayer
    if (unlikely(mb != 0 || me != 31)) {
1749 76a66253 j_mayer
#if defined(TARGET_PPC64)
1750 76a66253 j_mayer
        mb += 32;
1751 76a66253 j_mayer
        me += 32;
1752 76a66253 j_mayer
#endif
1753 54843a58 aurel32
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1754 d03ef511 aurel32
    } else {
1755 54843a58 aurel32
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1756 79aceca5 bellard
    }
1757 54843a58 aurel32
    tcg_temp_free(t0);
1758 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
1759 d03ef511 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1760 79aceca5 bellard
}
1761 79aceca5 bellard
1762 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1763 d9bce9d9 j_mayer
#define GEN_PPC64_R2(name, opc1, opc2)                                        \
1764 c7697e1f j_mayer
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1765 d9bce9d9 j_mayer
{                                                                             \
1766 d9bce9d9 j_mayer
    gen_##name(ctx, 0);                                                       \
1767 d9bce9d9 j_mayer
}                                                                             \
1768 c7697e1f j_mayer
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
1769 c7697e1f j_mayer
             PPC_64B)                                                         \
1770 d9bce9d9 j_mayer
{                                                                             \
1771 d9bce9d9 j_mayer
    gen_##name(ctx, 1);                                                       \
1772 d9bce9d9 j_mayer
}
1773 d9bce9d9 j_mayer
#define GEN_PPC64_R4(name, opc1, opc2)                                        \
1774 c7697e1f j_mayer
GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1775 d9bce9d9 j_mayer
{                                                                             \
1776 d9bce9d9 j_mayer
    gen_##name(ctx, 0, 0);                                                    \
1777 d9bce9d9 j_mayer
}                                                                             \
1778 c7697e1f j_mayer
GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
1779 c7697e1f j_mayer
             PPC_64B)                                                         \
1780 d9bce9d9 j_mayer
{                                                                             \
1781 d9bce9d9 j_mayer
    gen_##name(ctx, 0, 1);                                                    \
1782 d9bce9d9 j_mayer
}                                                                             \
1783 c7697e1f j_mayer
GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
1784 c7697e1f j_mayer
             PPC_64B)                                                         \
1785 d9bce9d9 j_mayer
{                                                                             \
1786 d9bce9d9 j_mayer
    gen_##name(ctx, 1, 0);                                                    \
1787 d9bce9d9 j_mayer
}                                                                             \
1788 c7697e1f j_mayer
GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000,   \
1789 c7697e1f j_mayer
             PPC_64B)                                                         \
1790 d9bce9d9 j_mayer
{                                                                             \
1791 d9bce9d9 j_mayer
    gen_##name(ctx, 1, 1);                                                    \
1792 d9bce9d9 j_mayer
}
1793 51789c41 j_mayer
1794 b068d6a7 j_mayer
static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
1795 b068d6a7 j_mayer
                                      uint32_t me, uint32_t sh)
1796 51789c41 j_mayer
{
1797 d03ef511 aurel32
    if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
1798 d03ef511 aurel32
        tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1799 d03ef511 aurel32
    } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
1800 d03ef511 aurel32
        tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
1801 d03ef511 aurel32
    } else {
1802 a7812ae4 pbrook
        TCGv t0 = tcg_temp_new();
1803 54843a58 aurel32
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1804 d03ef511 aurel32
        if (likely(mb == 0 && me == 63)) {
1805 54843a58 aurel32
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1806 d03ef511 aurel32
        } else {
1807 d03ef511 aurel32
            tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1808 51789c41 j_mayer
        }
1809 d03ef511 aurel32
        tcg_temp_free(t0);
1810 51789c41 j_mayer
    }
1811 51789c41 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
1812 d03ef511 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1813 51789c41 j_mayer
}
1814 d9bce9d9 j_mayer
/* rldicl - rldicl. */
1815 b068d6a7 j_mayer
static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1816 d9bce9d9 j_mayer
{
1817 51789c41 j_mayer
    uint32_t sh, mb;
1818 d9bce9d9 j_mayer
1819 9d53c753 j_mayer
    sh = SH(ctx->opcode) | (shn << 5);
1820 9d53c753 j_mayer
    mb = MB(ctx->opcode) | (mbn << 5);
1821 51789c41 j_mayer
    gen_rldinm(ctx, mb, 63, sh);
1822 d9bce9d9 j_mayer
}
1823 51789c41 j_mayer
GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1824 d9bce9d9 j_mayer
/* rldicr - rldicr. */
1825 b068d6a7 j_mayer
static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1826 d9bce9d9 j_mayer
{
1827 51789c41 j_mayer
    uint32_t sh, me;
1828 d9bce9d9 j_mayer
1829 9d53c753 j_mayer
    sh = SH(ctx->opcode) | (shn << 5);
1830 9d53c753 j_mayer
    me = MB(ctx->opcode) | (men << 5);
1831 51789c41 j_mayer
    gen_rldinm(ctx, 0, me, sh);
1832 d9bce9d9 j_mayer
}
1833 51789c41 j_mayer
GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1834 d9bce9d9 j_mayer
/* rldic - rldic. */
1835 b068d6a7 j_mayer
static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1836 d9bce9d9 j_mayer
{
1837 51789c41 j_mayer
    uint32_t sh, mb;
1838 d9bce9d9 j_mayer
1839 9d53c753 j_mayer
    sh = SH(ctx->opcode) | (shn << 5);
1840 9d53c753 j_mayer
    mb = MB(ctx->opcode) | (mbn << 5);
1841 51789c41 j_mayer
    gen_rldinm(ctx, mb, 63 - sh, sh);
1842 51789c41 j_mayer
}
1843 51789c41 j_mayer
GEN_PPC64_R4(rldic, 0x1E, 0x04);
1844 51789c41 j_mayer
1845 b068d6a7 j_mayer
static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
1846 b068d6a7 j_mayer
                                     uint32_t me)
1847 51789c41 j_mayer
{
1848 54843a58 aurel32
    TCGv t0;
1849 d03ef511 aurel32
1850 d03ef511 aurel32
    mb = MB(ctx->opcode);
1851 d03ef511 aurel32
    me = ME(ctx->opcode);
1852 a7812ae4 pbrook
    t0 = tcg_temp_new();
1853 d03ef511 aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1854 54843a58 aurel32
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1855 51789c41 j_mayer
    if (unlikely(mb != 0 || me != 63)) {
1856 54843a58 aurel32
        tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1857 54843a58 aurel32
    } else {
1858 54843a58 aurel32
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1859 54843a58 aurel32
    }
1860 54843a58 aurel32
    tcg_temp_free(t0);
1861 51789c41 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
1862 d03ef511 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1863 d9bce9d9 j_mayer
}
1864 51789c41 j_mayer
1865 d9bce9d9 j_mayer
/* rldcl - rldcl. */
1866 b068d6a7 j_mayer
static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1867 d9bce9d9 j_mayer
{
1868 51789c41 j_mayer
    uint32_t mb;
1869 d9bce9d9 j_mayer
1870 9d53c753 j_mayer
    mb = MB(ctx->opcode) | (mbn << 5);
1871 51789c41 j_mayer
    gen_rldnm(ctx, mb, 63);
1872 d9bce9d9 j_mayer
}
1873 36081602 j_mayer
GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1874 d9bce9d9 j_mayer
/* rldcr - rldcr. */
1875 b068d6a7 j_mayer
static always_inline void gen_rldcr (DisasContext *ctx, int men)
1876 d9bce9d9 j_mayer
{
1877 51789c41 j_mayer
    uint32_t me;
1878 d9bce9d9 j_mayer
1879 9d53c753 j_mayer
    me = MB(ctx->opcode) | (men << 5);
1880 51789c41 j_mayer
    gen_rldnm(ctx, 0, me);
1881 d9bce9d9 j_mayer
}
1882 36081602 j_mayer
GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1883 d9bce9d9 j_mayer
/* rldimi - rldimi. */
1884 b068d6a7 j_mayer
static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1885 d9bce9d9 j_mayer
{
1886 271a916e j_mayer
    uint32_t sh, mb, me;
1887 d9bce9d9 j_mayer
1888 9d53c753 j_mayer
    sh = SH(ctx->opcode) | (shn << 5);
1889 9d53c753 j_mayer
    mb = MB(ctx->opcode) | (mbn << 5);
1890 271a916e j_mayer
    me = 63 - sh;
1891 d03ef511 aurel32
    if (unlikely(sh == 0 && mb == 0)) {
1892 d03ef511 aurel32
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1893 d03ef511 aurel32
    } else {
1894 d03ef511 aurel32
        TCGv t0, t1;
1895 d03ef511 aurel32
        target_ulong mask;
1896 d03ef511 aurel32
1897 a7812ae4 pbrook
        t0 = tcg_temp_new();
1898 54843a58 aurel32
        tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
1899 a7812ae4 pbrook
        t1 = tcg_temp_new();
1900 d03ef511 aurel32
        mask = MASK(mb, me);
1901 d03ef511 aurel32
        tcg_gen_andi_tl(t0, t0, mask);
1902 d03ef511 aurel32
        tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1903 d03ef511 aurel32
        tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1904 d03ef511 aurel32
        tcg_temp_free(t0);
1905 d03ef511 aurel32
        tcg_temp_free(t1);
1906 51789c41 j_mayer
    }
1907 51789c41 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
1908 d03ef511 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1909 d9bce9d9 j_mayer
}
1910 36081602 j_mayer
GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1911 d9bce9d9 j_mayer
#endif
1912 d9bce9d9 j_mayer
1913 79aceca5 bellard
/***                             Integer shift                             ***/
1914 79aceca5 bellard
/* slw & slw. */
1915 26d67362 aurel32
GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER)
1916 26d67362 aurel32
{
1917 fea0c503 aurel32
    TCGv t0;
1918 26d67362 aurel32
    int l1, l2;
1919 26d67362 aurel32
    l1 = gen_new_label();
1920 26d67362 aurel32
    l2 = gen_new_label();
1921 26d67362 aurel32
1922 a7812ae4 pbrook
    t0 = tcg_temp_local_new();
1923 0cfe58cd aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1924 0cfe58cd aurel32
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
1925 26d67362 aurel32
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1926 26d67362 aurel32
    tcg_gen_br(l2);
1927 26d67362 aurel32
    gen_set_label(l1);
1928 fea0c503 aurel32
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
1929 26d67362 aurel32
    tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1930 26d67362 aurel32
    gen_set_label(l2);
1931 fea0c503 aurel32
    tcg_temp_free(t0);
1932 26d67362 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1933 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1934 26d67362 aurel32
}
1935 79aceca5 bellard
/* sraw & sraw. */
1936 26d67362 aurel32
GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER)
1937 26d67362 aurel32
{
1938 a7812ae4 pbrook
    gen_helper_sraw(cpu_gpr[rA(ctx->opcode)],
1939 a7812ae4 pbrook
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1940 26d67362 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1941 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1942 26d67362 aurel32
}
1943 79aceca5 bellard
/* srawi & srawi. */
1944 79aceca5 bellard
GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
1945 79aceca5 bellard
{
1946 26d67362 aurel32
    int sh = SH(ctx->opcode);
1947 26d67362 aurel32
    if (sh != 0) {
1948 26d67362 aurel32
        int l1, l2;
1949 fea0c503 aurel32
        TCGv t0;
1950 26d67362 aurel32
        l1 = gen_new_label();
1951 26d67362 aurel32
        l2 = gen_new_label();
1952 a7812ae4 pbrook
        t0 = tcg_temp_local_new();
1953 fea0c503 aurel32
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1954 fea0c503 aurel32
        tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
1955 fea0c503 aurel32
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1956 fea0c503 aurel32
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1957 269f3e95 aurel32
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
1958 26d67362 aurel32
        tcg_gen_br(l2);
1959 26d67362 aurel32
        gen_set_label(l1);
1960 269f3e95 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1961 26d67362 aurel32
        gen_set_label(l2);
1962 fea0c503 aurel32
        tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1963 fea0c503 aurel32
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
1964 fea0c503 aurel32
        tcg_temp_free(t0);
1965 26d67362 aurel32
    } else {
1966 26d67362 aurel32
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1967 269f3e95 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1968 d9bce9d9 j_mayer
    }
1969 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
1970 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1971 79aceca5 bellard
}
1972 79aceca5 bellard
/* srw & srw. */
1973 26d67362 aurel32
GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER)
1974 26d67362 aurel32
{
1975 fea0c503 aurel32
    TCGv t0, t1;
1976 26d67362 aurel32
    int l1, l2;
1977 26d67362 aurel32
    l1 = gen_new_label();
1978 26d67362 aurel32
    l2 = gen_new_label();
1979 d9bce9d9 j_mayer
1980 a7812ae4 pbrook
    t0 = tcg_temp_local_new();
1981 0cfe58cd aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1982 0cfe58cd aurel32
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
1983 26d67362 aurel32
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1984 26d67362 aurel32
    tcg_gen_br(l2);
1985 26d67362 aurel32
    gen_set_label(l1);
1986 a7812ae4 pbrook
    t1 = tcg_temp_new();
1987 fea0c503 aurel32
    tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
1988 fea0c503 aurel32
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t1, t0);
1989 fea0c503 aurel32
    tcg_temp_free(t1);
1990 26d67362 aurel32
    gen_set_label(l2);
1991 fea0c503 aurel32
    tcg_temp_free(t0);
1992 26d67362 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
1993 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1994 26d67362 aurel32
}
1995 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1996 d9bce9d9 j_mayer
/* sld & sld. */
1997 26d67362 aurel32
GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B)
1998 26d67362 aurel32
{
1999 fea0c503 aurel32
    TCGv t0;
2000 26d67362 aurel32
    int l1, l2;
2001 26d67362 aurel32
    l1 = gen_new_label();
2002 26d67362 aurel32
    l2 = gen_new_label();
2003 26d67362 aurel32
2004 a7812ae4 pbrook
    t0 = tcg_temp_local_new();
2005 0cfe58cd aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
2006 0cfe58cd aurel32
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
2007 26d67362 aurel32
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
2008 26d67362 aurel32
    tcg_gen_br(l2);
2009 26d67362 aurel32
    gen_set_label(l1);
2010 fea0c503 aurel32
    tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
2011 26d67362 aurel32
    gen_set_label(l2);
2012 fea0c503 aurel32
    tcg_temp_free(t0);
2013 26d67362 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
2014 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2015 26d67362 aurel32
}
2016 d9bce9d9 j_mayer
/* srad & srad. */
2017 26d67362 aurel32
GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B)
2018 26d67362 aurel32
{
2019 a7812ae4 pbrook
    gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
2020 a7812ae4 pbrook
                    cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2021 26d67362 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
2022 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2023 26d67362 aurel32
}
2024 d9bce9d9 j_mayer
/* sradi & sradi. */
2025 b068d6a7 j_mayer
static always_inline void gen_sradi (DisasContext *ctx, int n)
2026 d9bce9d9 j_mayer
{
2027 26d67362 aurel32
    int sh = SH(ctx->opcode) + (n << 5);
2028 d9bce9d9 j_mayer
    if (sh != 0) {
2029 26d67362 aurel32
        int l1, l2;
2030 fea0c503 aurel32
        TCGv t0;
2031 26d67362 aurel32
        l1 = gen_new_label();
2032 26d67362 aurel32
        l2 = gen_new_label();
2033 a7812ae4 pbrook
        t0 = tcg_temp_local_new();
2034 26d67362 aurel32
        tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
2035 fea0c503 aurel32
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
2036 fea0c503 aurel32
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2037 269f3e95 aurel32
        tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
2038 26d67362 aurel32
        tcg_gen_br(l2);
2039 26d67362 aurel32
        gen_set_label(l1);
2040 269f3e95 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
2041 26d67362 aurel32
        gen_set_label(l2);
2042 a9730017 aurel32
        tcg_temp_free(t0);
2043 26d67362 aurel32
        tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
2044 26d67362 aurel32
    } else {
2045 26d67362 aurel32
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2046 269f3e95 aurel32
        tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
2047 d9bce9d9 j_mayer
    }
2048 d9bce9d9 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
2049 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2050 d9bce9d9 j_mayer
}
2051 c7697e1f j_mayer
GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
2052 d9bce9d9 j_mayer
{
2053 d9bce9d9 j_mayer
    gen_sradi(ctx, 0);
2054 d9bce9d9 j_mayer
}
2055 c7697e1f j_mayer
GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
2056 d9bce9d9 j_mayer
{
2057 d9bce9d9 j_mayer
    gen_sradi(ctx, 1);
2058 d9bce9d9 j_mayer
}
2059 d9bce9d9 j_mayer
/* srd & srd. */
2060 26d67362 aurel32
GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B)
2061 26d67362 aurel32
{
2062 fea0c503 aurel32
    TCGv t0;
2063 26d67362 aurel32
    int l1, l2;
2064 26d67362 aurel32
    l1 = gen_new_label();
2065 26d67362 aurel32
    l2 = gen_new_label();
2066 26d67362 aurel32
2067 a7812ae4 pbrook
    t0 = tcg_temp_local_new();
2068 0cfe58cd aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
2069 0cfe58cd aurel32
    tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
2070 26d67362 aurel32
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
2071 26d67362 aurel32
    tcg_gen_br(l2);
2072 26d67362 aurel32
    gen_set_label(l1);
2073 fea0c503 aurel32
    tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
2074 26d67362 aurel32
    gen_set_label(l2);
2075 fea0c503 aurel32
    tcg_temp_free(t0);
2076 26d67362 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
2077 26d67362 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2078 26d67362 aurel32
}
2079 d9bce9d9 j_mayer
#endif
2080 79aceca5 bellard
2081 79aceca5 bellard
/***                       Floating-Point arithmetic                       ***/
2082 7c58044c j_mayer
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
2083 a750fc0b j_mayer
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
2084 9a64fbe4 bellard
{                                                                             \
2085 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2086 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
2087 3cc62370 bellard
        return;                                                               \
2088 3cc62370 bellard
    }                                                                         \
2089 7c58044c j_mayer
    gen_reset_fpstatus();                                                     \
2090 af12906f aurel32
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
2091 af12906f aurel32
                     cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
2092 4ecc3190 bellard
    if (isfloat) {                                                            \
2093 af12906f aurel32
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2094 4ecc3190 bellard
    }                                                                         \
2095 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf,                      \
2096 af12906f aurel32
                     Rc(ctx->opcode) != 0);                                   \
2097 9a64fbe4 bellard
}
2098 9a64fbe4 bellard
2099 7c58044c j_mayer
#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
2100 7c58044c j_mayer
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
2101 7c58044c j_mayer
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
2102 9a64fbe4 bellard
2103 7c58044c j_mayer
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2104 7c58044c j_mayer
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2105 9a64fbe4 bellard
{                                                                             \
2106 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2107 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
2108 3cc62370 bellard
        return;                                                               \
2109 3cc62370 bellard
    }                                                                         \
2110 7c58044c j_mayer
    gen_reset_fpstatus();                                                     \
2111 af12906f aurel32
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
2112 af12906f aurel32
                     cpu_fpr[rB(ctx->opcode)]);                               \
2113 4ecc3190 bellard
    if (isfloat) {                                                            \
2114 af12906f aurel32
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2115 4ecc3190 bellard
    }                                                                         \
2116 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2117 af12906f aurel32
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2118 9a64fbe4 bellard
}
2119 7c58044c j_mayer
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
2120 7c58044c j_mayer
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2121 7c58044c j_mayer
_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2122 9a64fbe4 bellard
2123 7c58044c j_mayer
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
2124 7c58044c j_mayer
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
2125 9a64fbe4 bellard
{                                                                             \
2126 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2127 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
2128 3cc62370 bellard
        return;                                                               \
2129 3cc62370 bellard
    }                                                                         \
2130 7c58044c j_mayer
    gen_reset_fpstatus();                                                     \
2131 af12906f aurel32
    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],      \
2132 af12906f aurel32
                       cpu_fpr[rC(ctx->opcode)]);                             \
2133 4ecc3190 bellard
    if (isfloat) {                                                            \
2134 af12906f aurel32
        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);  \
2135 4ecc3190 bellard
    }                                                                         \
2136 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2137 af12906f aurel32
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2138 9a64fbe4 bellard
}
2139 7c58044c j_mayer
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
2140 7c58044c j_mayer
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
2141 7c58044c j_mayer
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
2142 9a64fbe4 bellard
2143 7c58044c j_mayer
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
2144 a750fc0b j_mayer
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
2145 9a64fbe4 bellard
{                                                                             \
2146 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2147 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
2148 3cc62370 bellard
        return;                                                               \
2149 3cc62370 bellard
    }                                                                         \
2150 7c58044c j_mayer
    gen_reset_fpstatus();                                                     \
2151 af12906f aurel32
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2152 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2153 af12906f aurel32
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2154 79aceca5 bellard
}
2155 79aceca5 bellard
2156 7c58044c j_mayer
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
2157 a750fc0b j_mayer
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)                        \
2158 9a64fbe4 bellard
{                                                                             \
2159 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
2160 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
2161 3cc62370 bellard
        return;                                                               \
2162 3cc62370 bellard
    }                                                                         \
2163 7c58044c j_mayer
    gen_reset_fpstatus();                                                     \
2164 af12906f aurel32
    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);   \
2165 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)],                                \
2166 af12906f aurel32
                     set_fprf, Rc(ctx->opcode) != 0);                         \
2167 79aceca5 bellard
}
2168 79aceca5 bellard
2169 9a64fbe4 bellard
/* fadd - fadds */
2170 7c58044c j_mayer
GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
2171 4ecc3190 bellard
/* fdiv - fdivs */
2172 7c58044c j_mayer
GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
2173 4ecc3190 bellard
/* fmul - fmuls */
2174 7c58044c j_mayer
GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
2175 79aceca5 bellard
2176 d7e4b87e j_mayer
/* fre */
2177 7c58044c j_mayer
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
2178 d7e4b87e j_mayer
2179 a750fc0b j_mayer
/* fres */
2180 7c58044c j_mayer
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
2181 79aceca5 bellard
2182 a750fc0b j_mayer
/* frsqrte */
2183 7c58044c j_mayer
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2184 7c58044c j_mayer
2185 7c58044c j_mayer
/* frsqrtes */
2186 af12906f aurel32
GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES)
2187 7c58044c j_mayer
{
2188 af12906f aurel32
    if (unlikely(!ctx->fpu_enabled)) {
2189 af12906f aurel32
        GEN_EXCP_NO_FP(ctx);
2190 af12906f aurel32
        return;
2191 af12906f aurel32
    }
2192 af12906f aurel32
    gen_reset_fpstatus();
2193 af12906f aurel32
    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2194 af12906f aurel32
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2195 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2196 7c58044c j_mayer
}
2197 79aceca5 bellard
2198 a750fc0b j_mayer
/* fsel */
2199 7c58044c j_mayer
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
2200 4ecc3190 bellard
/* fsub - fsubs */
2201 7c58044c j_mayer
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
2202 79aceca5 bellard
/* Optional: */
2203 79aceca5 bellard
/* fsqrt */
2204 a750fc0b j_mayer
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
2205 c7d344af bellard
{
2206 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2207 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2208 c7d344af bellard
        return;
2209 c7d344af bellard
    }
2210 7c58044c j_mayer
    gen_reset_fpstatus();
2211 af12906f aurel32
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2212 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2213 c7d344af bellard
}
2214 79aceca5 bellard
2215 a750fc0b j_mayer
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
2216 79aceca5 bellard
{
2217 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2218 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2219 3cc62370 bellard
        return;
2220 3cc62370 bellard
    }
2221 7c58044c j_mayer
    gen_reset_fpstatus();
2222 af12906f aurel32
    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2223 af12906f aurel32
    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2224 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
2225 79aceca5 bellard
}
2226 79aceca5 bellard
2227 79aceca5 bellard
/***                     Floating-Point multiply-and-add                   ***/
2228 4ecc3190 bellard
/* fmadd - fmadds */
2229 7c58044c j_mayer
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
2230 4ecc3190 bellard
/* fmsub - fmsubs */
2231 7c58044c j_mayer
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
2232 4ecc3190 bellard
/* fnmadd - fnmadds */
2233 7c58044c j_mayer
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
2234 4ecc3190 bellard
/* fnmsub - fnmsubs */
2235 7c58044c j_mayer
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
2236 79aceca5 bellard
2237 79aceca5 bellard
/***                     Floating-Point round & convert                    ***/
2238 79aceca5 bellard
/* fctiw */
2239 7c58044c j_mayer
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
2240 79aceca5 bellard
/* fctiwz */
2241 7c58044c j_mayer
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
2242 79aceca5 bellard
/* frsp */
2243 7c58044c j_mayer
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
2244 426613db j_mayer
#if defined(TARGET_PPC64)
2245 426613db j_mayer
/* fcfid */
2246 7c58044c j_mayer
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
2247 426613db j_mayer
/* fctid */
2248 7c58044c j_mayer
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
2249 426613db j_mayer
/* fctidz */
2250 7c58044c j_mayer
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
2251 426613db j_mayer
#endif
2252 79aceca5 bellard
2253 d7e4b87e j_mayer
/* frin */
2254 7c58044c j_mayer
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
2255 d7e4b87e j_mayer
/* friz */
2256 7c58044c j_mayer
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
2257 d7e4b87e j_mayer
/* frip */
2258 7c58044c j_mayer
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
2259 d7e4b87e j_mayer
/* frim */
2260 7c58044c j_mayer
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
2261 d7e4b87e j_mayer
2262 79aceca5 bellard
/***                         Floating-Point compare                        ***/
2263 79aceca5 bellard
/* fcmpo */
2264 76a66253 j_mayer
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
2265 79aceca5 bellard
{
2266 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2267 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2268 3cc62370 bellard
        return;
2269 3cc62370 bellard
    }
2270 7c58044c j_mayer
    gen_reset_fpstatus();
2271 af12906f aurel32
    gen_helper_fcmpo(cpu_crf[crfD(ctx->opcode)],
2272 af12906f aurel32
                     cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2273 af12906f aurel32
    gen_helper_float_check_status();
2274 79aceca5 bellard
}
2275 79aceca5 bellard
2276 79aceca5 bellard
/* fcmpu */
2277 76a66253 j_mayer
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
2278 79aceca5 bellard
{
2279 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2280 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2281 3cc62370 bellard
        return;
2282 3cc62370 bellard
    }
2283 7c58044c j_mayer
    gen_reset_fpstatus();
2284 af12906f aurel32
    gen_helper_fcmpu(cpu_crf[crfD(ctx->opcode)],
2285 af12906f aurel32
                     cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2286 af12906f aurel32
    gen_helper_float_check_status();
2287 79aceca5 bellard
}
2288 79aceca5 bellard
2289 9a64fbe4 bellard
/***                         Floating-point move                           ***/
2290 9a64fbe4 bellard
/* fabs */
2291 7c58044c j_mayer
/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2292 7c58044c j_mayer
GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
2293 9a64fbe4 bellard
2294 9a64fbe4 bellard
/* fmr  - fmr. */
2295 7c58044c j_mayer
/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
2296 9a64fbe4 bellard
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
2297 9a64fbe4 bellard
{
2298 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2299 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2300 3cc62370 bellard
        return;
2301 3cc62370 bellard
    }
2302 af12906f aurel32
    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2303 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2304 9a64fbe4 bellard
}
2305 9a64fbe4 bellard
2306 9a64fbe4 bellard
/* fnabs */
2307 7c58044c j_mayer
/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2308 7c58044c j_mayer
GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
2309 9a64fbe4 bellard
/* fneg */
2310 7c58044c j_mayer
/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2311 7c58044c j_mayer
GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
2312 9a64fbe4 bellard
2313 79aceca5 bellard
/***                  Floating-Point status & ctrl register                ***/
2314 79aceca5 bellard
/* mcrfs */
2315 79aceca5 bellard
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
2316 79aceca5 bellard
{
2317 7c58044c j_mayer
    int bfa;
2318 7c58044c j_mayer
2319 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2320 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2321 3cc62370 bellard
        return;
2322 3cc62370 bellard
    }
2323 7c58044c j_mayer
    gen_optimize_fprf();
2324 7c58044c j_mayer
    bfa = 4 * (7 - crfS(ctx->opcode));
2325 e1571908 aurel32
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
2326 e1571908 aurel32
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
2327 af12906f aurel32
    tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
2328 79aceca5 bellard
}
2329 79aceca5 bellard
2330 79aceca5 bellard
/* mffs */
2331 79aceca5 bellard
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
2332 79aceca5 bellard
{
2333 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2334 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2335 3cc62370 bellard
        return;
2336 3cc62370 bellard
    }
2337 7c58044c j_mayer
    gen_optimize_fprf();
2338 7c58044c j_mayer
    gen_reset_fpstatus();
2339 af12906f aurel32
    tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2340 af12906f aurel32
    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2341 79aceca5 bellard
}
2342 79aceca5 bellard
2343 79aceca5 bellard
/* mtfsb0 */
2344 79aceca5 bellard
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
2345 79aceca5 bellard
{
2346 fb0eaffc bellard
    uint8_t crb;
2347 3b46e624 ths
2348 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2349 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2350 3cc62370 bellard
        return;
2351 3cc62370 bellard
    }
2352 7c58044c j_mayer
    crb = 32 - (crbD(ctx->opcode) >> 2);
2353 7c58044c j_mayer
    gen_optimize_fprf();
2354 7c58044c j_mayer
    gen_reset_fpstatus();
2355 7c58044c j_mayer
    if (likely(crb != 30 && crb != 29))
2356 af12906f aurel32
        tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(1 << crb));
2357 7c58044c j_mayer
    if (unlikely(Rc(ctx->opcode) != 0)) {
2358 e1571908 aurel32
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2359 7c58044c j_mayer
    }
2360 79aceca5 bellard
}
2361 79aceca5 bellard
2362 79aceca5 bellard
/* mtfsb1 */
2363 79aceca5 bellard
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
2364 79aceca5 bellard
{
2365 fb0eaffc bellard
    uint8_t crb;
2366 3b46e624 ths
2367 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2368 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2369 3cc62370 bellard
        return;
2370 3cc62370 bellard
    }
2371 7c58044c j_mayer
    crb = 32 - (crbD(ctx->opcode) >> 2);
2372 7c58044c j_mayer
    gen_optimize_fprf();
2373 7c58044c j_mayer
    gen_reset_fpstatus();
2374 7c58044c j_mayer
    /* XXX: we pretend we can only do IEEE floating-point computations */
2375 af12906f aurel32
    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
2376 0f2f39c2 aurel32
        TCGv_i32 t0 = tcg_const_i32(crb);
2377 af12906f aurel32
        gen_helper_fpscr_setbit(t0);
2378 0f2f39c2 aurel32
        tcg_temp_free_i32(t0);
2379 af12906f aurel32
    }
2380 7c58044c j_mayer
    if (unlikely(Rc(ctx->opcode) != 0)) {
2381 e1571908 aurel32
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2382 7c58044c j_mayer
    }
2383 7c58044c j_mayer
    /* We can raise a differed exception */
2384 af12906f aurel32
    gen_helper_float_check_status();
2385 79aceca5 bellard
}
2386 79aceca5 bellard
2387 79aceca5 bellard
/* mtfsf */
2388 79aceca5 bellard
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
2389 79aceca5 bellard
{
2390 0f2f39c2 aurel32
    TCGv_i32 t0;
2391 af12906f aurel32
2392 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2393 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2394 3cc62370 bellard
        return;
2395 3cc62370 bellard
    }
2396 7c58044c j_mayer
    gen_optimize_fprf();
2397 7c58044c j_mayer
    gen_reset_fpstatus();
2398 af12906f aurel32
    t0 = tcg_const_i32(FM(ctx->opcode));
2399 af12906f aurel32
    gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
2400 0f2f39c2 aurel32
    tcg_temp_free_i32(t0);
2401 7c58044c j_mayer
    if (unlikely(Rc(ctx->opcode) != 0)) {
2402 e1571908 aurel32
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2403 7c58044c j_mayer
    }
2404 7c58044c j_mayer
    /* We can raise a differed exception */
2405 af12906f aurel32
    gen_helper_float_check_status();
2406 79aceca5 bellard
}
2407 79aceca5 bellard
2408 79aceca5 bellard
/* mtfsfi */
2409 79aceca5 bellard
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
2410 79aceca5 bellard
{
2411 7c58044c j_mayer
    int bf, sh;
2412 0f2f39c2 aurel32
    TCGv_i64 t0;
2413 0f2f39c2 aurel32
    TCGv_i32 t1;
2414 7c58044c j_mayer
2415 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {
2416 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);
2417 3cc62370 bellard
        return;
2418 3cc62370 bellard
    }
2419 7c58044c j_mayer
    bf = crbD(ctx->opcode) >> 2;
2420 7c58044c j_mayer
    sh = 7 - bf;
2421 7c58044c j_mayer
    gen_optimize_fprf();
2422 7c58044c j_mayer
    gen_reset_fpstatus();
2423 0f2f39c2 aurel32
    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
2424 af12906f aurel32
    t1 = tcg_const_i32(1 << sh);
2425 af12906f aurel32
    gen_helper_store_fpscr(t0, t1);
2426 0f2f39c2 aurel32
    tcg_temp_free_i64(t0);
2427 0f2f39c2 aurel32
    tcg_temp_free_i32(t1);
2428 7c58044c j_mayer
    if (unlikely(Rc(ctx->opcode) != 0)) {
2429 e1571908 aurel32
        tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
2430 7c58044c j_mayer
    }
2431 7c58044c j_mayer
    /* We can raise a differed exception */
2432 af12906f aurel32
    gen_helper_float_check_status();
2433 79aceca5 bellard
}
2434 79aceca5 bellard
2435 76a66253 j_mayer
/***                           Addressing modes                            ***/
2436 76a66253 j_mayer
/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2437 76db3ba4 aurel32
static always_inline void gen_addr_imm_index (DisasContext *ctx, TCGv EA, target_long maskl)
2438 76a66253 j_mayer
{
2439 76a66253 j_mayer
    target_long simm = SIMM(ctx->opcode);
2440 76a66253 j_mayer
2441 be147d08 j_mayer
    simm &= ~maskl;
2442 76db3ba4 aurel32
    if (rA(ctx->opcode) == 0) {
2443 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2444 76db3ba4 aurel32
        if (!ctx->sf_mode) {
2445 76db3ba4 aurel32
            tcg_gen_movi_tl(EA, (uint32_t)simm);
2446 76db3ba4 aurel32
        } else
2447 76db3ba4 aurel32
#endif
2448 e2be8d8d aurel32
        tcg_gen_movi_tl(EA, simm);
2449 76db3ba4 aurel32
    } else if (likely(simm != 0)) {
2450 e2be8d8d aurel32
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2451 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2452 76db3ba4 aurel32
        if (!ctx->sf_mode) {
2453 76db3ba4 aurel32
            tcg_gen_ext32u_tl(EA, EA);
2454 76db3ba4 aurel32
        }
2455 76db3ba4 aurel32
#endif
2456 76db3ba4 aurel32
    } else {
2457 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2458 76db3ba4 aurel32
        if (!ctx->sf_mode) {
2459 76db3ba4 aurel32
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2460 76db3ba4 aurel32
        } else
2461 76db3ba4 aurel32
#endif
2462 e2be8d8d aurel32
        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2463 76db3ba4 aurel32
    }
2464 76a66253 j_mayer
}
2465 76a66253 j_mayer
2466 76db3ba4 aurel32
static always_inline void gen_addr_reg_index (DisasContext *ctx, TCGv EA)
2467 76a66253 j_mayer
{
2468 76db3ba4 aurel32
    if (rA(ctx->opcode) == 0) {
2469 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2470 76db3ba4 aurel32
        if (!ctx->sf_mode) {
2471 76db3ba4 aurel32
            tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2472 76db3ba4 aurel32
        } else
2473 76db3ba4 aurel32
#endif
2474 e2be8d8d aurel32
        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2475 76db3ba4 aurel32
    } else {
2476 e2be8d8d aurel32
        tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2477 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2478 76db3ba4 aurel32
        if (!ctx->sf_mode) {
2479 76db3ba4 aurel32
            tcg_gen_ext32u_tl(EA, EA);
2480 76db3ba4 aurel32
        }
2481 76db3ba4 aurel32
#endif
2482 76db3ba4 aurel32
    }
2483 76a66253 j_mayer
}
2484 76a66253 j_mayer
2485 76db3ba4 aurel32
static always_inline void gen_addr_register (DisasContext *ctx, TCGv EA)
2486 76a66253 j_mayer
{
2487 76db3ba4 aurel32
    if (rA(ctx->opcode) == 0) {
2488 e2be8d8d aurel32
        tcg_gen_movi_tl(EA, 0);
2489 76db3ba4 aurel32
    } else {
2490 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2491 76db3ba4 aurel32
        if (!ctx->sf_mode) {
2492 76db3ba4 aurel32
            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2493 76db3ba4 aurel32
        } else
2494 76db3ba4 aurel32
#endif
2495 76db3ba4 aurel32
            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2496 76db3ba4 aurel32
    }
2497 76db3ba4 aurel32
}
2498 76db3ba4 aurel32
2499 76db3ba4 aurel32
static always_inline void gen_addr_add (DisasContext *ctx, TCGv ret, TCGv arg1, target_long val)
2500 76db3ba4 aurel32
{
2501 76db3ba4 aurel32
    tcg_gen_addi_tl(ret, arg1, val);
2502 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2503 76db3ba4 aurel32
    if (!ctx->sf_mode) {
2504 76db3ba4 aurel32
        tcg_gen_ext32u_tl(ret, ret);
2505 76db3ba4 aurel32
    }
2506 76db3ba4 aurel32
#endif
2507 76a66253 j_mayer
}
2508 76a66253 j_mayer
2509 cf360a32 aurel32
static always_inline void gen_check_align (DisasContext *ctx, TCGv EA, int mask)
2510 cf360a32 aurel32
{
2511 cf360a32 aurel32
    int l1 = gen_new_label();
2512 cf360a32 aurel32
    TCGv t0 = tcg_temp_new();
2513 cf360a32 aurel32
    TCGv_i32 t1, t2;
2514 cf360a32 aurel32
    /* NIP cannot be restored if the memory exception comes from an helper */
2515 cf360a32 aurel32
    gen_update_nip(ctx, ctx->nip - 4);
2516 cf360a32 aurel32
    tcg_gen_andi_tl(t0, EA, mask);
2517 cf360a32 aurel32
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2518 cf360a32 aurel32
    t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2519 cf360a32 aurel32
    t2 = tcg_const_i32(0);
2520 cf360a32 aurel32
    gen_helper_raise_exception_err(t1, t2);
2521 cf360a32 aurel32
    tcg_temp_free_i32(t1);
2522 cf360a32 aurel32
    tcg_temp_free_i32(t2);
2523 cf360a32 aurel32
    gen_set_label(l1);
2524 cf360a32 aurel32
    tcg_temp_free(t0);
2525 cf360a32 aurel32
}
2526 cf360a32 aurel32
2527 7863667f j_mayer
/***                             Integer load                              ***/
2528 76db3ba4 aurel32
static always_inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2529 76db3ba4 aurel32
{
2530 76db3ba4 aurel32
    tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2531 76db3ba4 aurel32
}
2532 76db3ba4 aurel32
2533 76db3ba4 aurel32
static always_inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2534 76db3ba4 aurel32
{
2535 76db3ba4 aurel32
    tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
2536 76db3ba4 aurel32
}
2537 76db3ba4 aurel32
2538 76db3ba4 aurel32
static always_inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2539 76db3ba4 aurel32
{
2540 76db3ba4 aurel32
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2541 76db3ba4 aurel32
    if (unlikely(ctx->le_mode)) {
2542 b61f2753 aurel32
#if defined(TARGET_PPC64)
2543 76db3ba4 aurel32
        TCGv_i32 t0 = tcg_temp_new_i32();
2544 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
2545 ea363694 aurel32
        tcg_gen_bswap16_i32(t0, t0);
2546 76db3ba4 aurel32
        tcg_gen_extu_i32_tl(arg1, t0);
2547 a7812ae4 pbrook
        tcg_temp_free_i32(t0);
2548 76db3ba4 aurel32
#else
2549 76db3ba4 aurel32
        tcg_gen_bswap16_i32(arg1, arg1);
2550 76db3ba4 aurel32
#endif
2551 76db3ba4 aurel32
    }
2552 b61f2753 aurel32
}
2553 b61f2753 aurel32
2554 76db3ba4 aurel32
static always_inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2555 b61f2753 aurel32
{
2556 76db3ba4 aurel32
    if (unlikely(ctx->le_mode)) {
2557 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2558 a7812ae4 pbrook
        TCGv_i32 t0;
2559 76db3ba4 aurel32
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2560 a7812ae4 pbrook
        t0 = tcg_temp_new_i32();
2561 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
2562 ea363694 aurel32
        tcg_gen_bswap16_i32(t0, t0);
2563 76db3ba4 aurel32
        tcg_gen_extu_i32_tl(arg1, t0);
2564 76db3ba4 aurel32
        tcg_gen_ext16s_tl(arg1, arg1);
2565 a7812ae4 pbrook
        tcg_temp_free_i32(t0);
2566 76db3ba4 aurel32
#else
2567 76db3ba4 aurel32
        tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2568 76db3ba4 aurel32
        tcg_gen_bswap16_i32(arg1, arg1);
2569 76db3ba4 aurel32
        tcg_gen_ext16s_i32(arg1, arg1);
2570 76db3ba4 aurel32
#endif
2571 76db3ba4 aurel32
    } else {
2572 76db3ba4 aurel32
        tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
2573 76db3ba4 aurel32
    }
2574 b61f2753 aurel32
}
2575 b61f2753 aurel32
2576 76db3ba4 aurel32
static always_inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
2577 b61f2753 aurel32
{
2578 76db3ba4 aurel32
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2579 76db3ba4 aurel32
    if (unlikely(ctx->le_mode)) {
2580 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2581 76db3ba4 aurel32
        TCGv_i32 t0 = tcg_temp_new_i32();
2582 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
2583 ea363694 aurel32
        tcg_gen_bswap_i32(t0, t0);
2584 76db3ba4 aurel32
        tcg_gen_extu_i32_tl(arg1, t0);
2585 a7812ae4 pbrook
        tcg_temp_free_i32(t0);
2586 76db3ba4 aurel32
#else
2587 76db3ba4 aurel32
        tcg_gen_bswap_i32(arg1, arg1);
2588 76db3ba4 aurel32
#endif
2589 76db3ba4 aurel32
    }
2590 b61f2753 aurel32
}
2591 b61f2753 aurel32
2592 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2593 76db3ba4 aurel32
static always_inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
2594 b61f2753 aurel32
{
2595 76db3ba4 aurel32
    if (unlikely(ctx->mem_idx)) {
2596 a7812ae4 pbrook
        TCGv_i32 t0;
2597 76db3ba4 aurel32
        tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2598 a7812ae4 pbrook
        t0 = tcg_temp_new_i32();
2599 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
2600 ea363694 aurel32
        tcg_gen_bswap_i32(t0, t0);
2601 76db3ba4 aurel32
        tcg_gen_ext_i32_tl(arg1, t0);
2602 a7812ae4 pbrook
        tcg_temp_free_i32(t0);
2603 b61f2753 aurel32
    } else
2604 76db3ba4 aurel32
        tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
2605 b61f2753 aurel32
}
2606 76db3ba4 aurel32
#endif
2607 b61f2753 aurel32
2608 76db3ba4 aurel32
static always_inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2609 b61f2753 aurel32
{
2610 76db3ba4 aurel32
    tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
2611 76db3ba4 aurel32
    if (unlikely(ctx->le_mode)) {
2612 76db3ba4 aurel32
        tcg_gen_bswap_i64(arg1, arg1);
2613 76db3ba4 aurel32
    }
2614 b61f2753 aurel32
}
2615 b61f2753 aurel32
2616 76db3ba4 aurel32
static always_inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
2617 b61f2753 aurel32
{
2618 76db3ba4 aurel32
    tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
2619 b61f2753 aurel32
}
2620 b61f2753 aurel32
2621 76db3ba4 aurel32
static always_inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
2622 b61f2753 aurel32
{
2623 76db3ba4 aurel32
    if (unlikely(ctx->le_mode)) {
2624 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2625 a7812ae4 pbrook
        TCGv_i32 t0;
2626 76db3ba4 aurel32
        TCGv t1;
2627 a7812ae4 pbrook
        t0 = tcg_temp_new_i32();
2628 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
2629 ea363694 aurel32
        tcg_gen_ext16u_i32(t0, t0);
2630 ea363694 aurel32
        tcg_gen_bswap16_i32(t0, t0);
2631 76db3ba4 aurel32
        t1 = tcg_temp_new();
2632 ea363694 aurel32
        tcg_gen_extu_i32_tl(t1, t0);
2633 a7812ae4 pbrook
        tcg_temp_free_i32(t0);
2634 76db3ba4 aurel32
        tcg_gen_qemu_st16(t1, arg2, ctx->mem_idx);
2635 76db3ba4 aurel32
        tcg_temp_free(t1);
2636 76db3ba4 aurel32
#else
2637 76db3ba4 aurel32
        TCGv t0 = tcg_temp_new();
2638 76db3ba4 aurel32
        tcg_gen_ext16u_tl(t0, arg1);
2639 76db3ba4 aurel32
        tcg_gen_bswap16_i32(t0, t0);
2640 76db3ba4 aurel32
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2641 76db3ba4 aurel32
        tcg_temp_free(t0);
2642 76db3ba4 aurel32
#endif
2643 76db3ba4 aurel32
    } else {
2644 76db3ba4 aurel32
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2645 76db3ba4 aurel32
    }
2646 b61f2753 aurel32
}
2647 b61f2753 aurel32
2648 76db3ba4 aurel32
static always_inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
2649 b61f2753 aurel32
{
2650 76db3ba4 aurel32
    if (unlikely(ctx->le_mode)) {
2651 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2652 a7812ae4 pbrook
        TCGv_i32 t0;
2653 76db3ba4 aurel32
        TCGv t1;
2654 a7812ae4 pbrook
        t0 = tcg_temp_new_i32();
2655 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
2656 ea363694 aurel32
        tcg_gen_bswap_i32(t0, t0);
2657 76db3ba4 aurel32
        t1 = tcg_temp_new();
2658 ea363694 aurel32
        tcg_gen_extu_i32_tl(t1, t0);
2659 a7812ae4 pbrook
        tcg_temp_free_i32(t0);
2660 76db3ba4 aurel32
        tcg_gen_qemu_st32(t1, arg2, ctx->mem_idx);
2661 76db3ba4 aurel32
        tcg_temp_free(t1);
2662 76db3ba4 aurel32
#else
2663 76db3ba4 aurel32
        TCGv t0 = tcg_temp_new_i32();
2664 76db3ba4 aurel32
        tcg_gen_bswap_i32(t0, arg1);
2665 76db3ba4 aurel32
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2666 76db3ba4 aurel32
        tcg_temp_free(t0);
2667 76db3ba4 aurel32
#endif
2668 76db3ba4 aurel32
    } else {
2669 76db3ba4 aurel32
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2670 76db3ba4 aurel32
    }
2671 b61f2753 aurel32
}
2672 b61f2753 aurel32
2673 76db3ba4 aurel32
static always_inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
2674 b61f2753 aurel32
{
2675 76db3ba4 aurel32
    if (unlikely(ctx->le_mode)) {
2676 a7812ae4 pbrook
        TCGv_i64 t0 = tcg_temp_new_i64();
2677 76db3ba4 aurel32
        tcg_gen_bswap_i64(t0, arg1);
2678 76db3ba4 aurel32
        tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
2679 a7812ae4 pbrook
        tcg_temp_free_i64(t0);
2680 b61f2753 aurel32
    } else
2681 76db3ba4 aurel32
        tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
2682 b61f2753 aurel32
}
2683 b61f2753 aurel32
2684 0c8aacd4 aurel32
#define GEN_LD(name, ldop, opc, type)                                         \
2685 0c8aacd4 aurel32
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
2686 79aceca5 bellard
{                                                                             \
2687 76db3ba4 aurel32
    TCGv EA;                                                                  \
2688 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2689 76db3ba4 aurel32
    EA = tcg_temp_new();                                                      \
2690 76db3ba4 aurel32
    gen_addr_imm_index(ctx, EA, 0);                                           \
2691 76db3ba4 aurel32
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2692 b61f2753 aurel32
    tcg_temp_free(EA);                                                        \
2693 79aceca5 bellard
}
2694 79aceca5 bellard
2695 0c8aacd4 aurel32
#define GEN_LDU(name, ldop, opc, type)                                        \
2696 0c8aacd4 aurel32
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
2697 79aceca5 bellard
{                                                                             \
2698 b61f2753 aurel32
    TCGv EA;                                                                  \
2699 76a66253 j_mayer
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2700 76a66253 j_mayer
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2701 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);                                                  \
2702 9fddaa0c bellard
        return;                                                               \
2703 9a64fbe4 bellard
    }                                                                         \
2704 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2705 0c8aacd4 aurel32
    EA = tcg_temp_new();                                                      \
2706 9d53c753 j_mayer
    if (type == PPC_64B)                                                      \
2707 76db3ba4 aurel32
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2708 9d53c753 j_mayer
    else                                                                      \
2709 76db3ba4 aurel32
        gen_addr_imm_index(ctx, EA, 0);                                       \
2710 76db3ba4 aurel32
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2711 b61f2753 aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2712 b61f2753 aurel32
    tcg_temp_free(EA);                                                        \
2713 79aceca5 bellard
}
2714 79aceca5 bellard
2715 0c8aacd4 aurel32
#define GEN_LDUX(name, ldop, opc2, opc3, type)                                \
2716 0c8aacd4 aurel32
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type)                     \
2717 79aceca5 bellard
{                                                                             \
2718 b61f2753 aurel32
    TCGv EA;                                                                  \
2719 76a66253 j_mayer
    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
2720 76a66253 j_mayer
                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
2721 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);                                                  \
2722 9fddaa0c bellard
        return;                                                               \
2723 9a64fbe4 bellard
    }                                                                         \
2724 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2725 0c8aacd4 aurel32
    EA = tcg_temp_new();                                                      \
2726 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
2727 76db3ba4 aurel32
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2728 b61f2753 aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2729 b61f2753 aurel32
    tcg_temp_free(EA);                                                        \
2730 79aceca5 bellard
}
2731 79aceca5 bellard
2732 0c8aacd4 aurel32
#define GEN_LDX(name, ldop, opc2, opc3, type)                                 \
2733 0c8aacd4 aurel32
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
2734 79aceca5 bellard
{                                                                             \
2735 76db3ba4 aurel32
    TCGv EA;                                                                  \
2736 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2737 76db3ba4 aurel32
    EA = tcg_temp_new();                                                      \
2738 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
2739 76db3ba4 aurel32
    gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);                       \
2740 b61f2753 aurel32
    tcg_temp_free(EA);                                                        \
2741 79aceca5 bellard
}
2742 79aceca5 bellard
2743 0c8aacd4 aurel32
#define GEN_LDS(name, ldop, op, type)                                         \
2744 0c8aacd4 aurel32
GEN_LD(name, ldop, op | 0x20, type);                                          \
2745 0c8aacd4 aurel32
GEN_LDU(name, ldop, op | 0x21, type);                                         \
2746 0c8aacd4 aurel32
GEN_LDUX(name, ldop, 0x17, op | 0x01, type);                                  \
2747 0c8aacd4 aurel32
GEN_LDX(name, ldop, 0x17, op | 0x00, type)
2748 79aceca5 bellard
2749 79aceca5 bellard
/* lbz lbzu lbzux lbzx */
2750 0c8aacd4 aurel32
GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
2751 79aceca5 bellard
/* lha lhau lhaux lhax */
2752 0c8aacd4 aurel32
GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
2753 79aceca5 bellard
/* lhz lhzu lhzux lhzx */
2754 0c8aacd4 aurel32
GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
2755 79aceca5 bellard
/* lwz lwzu lwzux lwzx */
2756 0c8aacd4 aurel32
GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
2757 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
2758 d9bce9d9 j_mayer
/* lwaux */
2759 0c8aacd4 aurel32
GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
2760 d9bce9d9 j_mayer
/* lwax */
2761 0c8aacd4 aurel32
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
2762 d9bce9d9 j_mayer
/* ldux */
2763 0c8aacd4 aurel32
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
2764 d9bce9d9 j_mayer
/* ldx */
2765 0c8aacd4 aurel32
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
2766 d9bce9d9 j_mayer
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
2767 d9bce9d9 j_mayer
{
2768 b61f2753 aurel32
    TCGv EA;
2769 d9bce9d9 j_mayer
    if (Rc(ctx->opcode)) {
2770 d9bce9d9 j_mayer
        if (unlikely(rA(ctx->opcode) == 0 ||
2771 d9bce9d9 j_mayer
                     rA(ctx->opcode) == rD(ctx->opcode))) {
2772 e1833e1f j_mayer
            GEN_EXCP_INVAL(ctx);
2773 d9bce9d9 j_mayer
            return;
2774 d9bce9d9 j_mayer
        }
2775 d9bce9d9 j_mayer
    }
2776 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);
2777 a7812ae4 pbrook
    EA = tcg_temp_new();
2778 76db3ba4 aurel32
    gen_addr_imm_index(ctx, EA, 0x03);
2779 d9bce9d9 j_mayer
    if (ctx->opcode & 0x02) {
2780 d9bce9d9 j_mayer
        /* lwa (lwau is undefined) */
2781 76db3ba4 aurel32
        gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2782 d9bce9d9 j_mayer
    } else {
2783 d9bce9d9 j_mayer
        /* ld - ldu */
2784 76db3ba4 aurel32
        gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
2785 d9bce9d9 j_mayer
    }
2786 d9bce9d9 j_mayer
    if (Rc(ctx->opcode))
2787 b61f2753 aurel32
        tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2788 b61f2753 aurel32
    tcg_temp_free(EA);
2789 d9bce9d9 j_mayer
}
2790 be147d08 j_mayer
/* lq */
2791 be147d08 j_mayer
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
2792 be147d08 j_mayer
{
2793 be147d08 j_mayer
#if defined(CONFIG_USER_ONLY)
2794 be147d08 j_mayer
    GEN_EXCP_PRIVOPC(ctx);
2795 be147d08 j_mayer
#else
2796 be147d08 j_mayer
    int ra, rd;
2797 b61f2753 aurel32
    TCGv EA;
2798 be147d08 j_mayer
2799 be147d08 j_mayer
    /* Restore CPU state */
2800 76db3ba4 aurel32
    if (unlikely(ctx->mem_idx == 0)) {
2801 be147d08 j_mayer
        GEN_EXCP_PRIVOPC(ctx);
2802 be147d08 j_mayer
        return;
2803 be147d08 j_mayer
    }
2804 be147d08 j_mayer
    ra = rA(ctx->opcode);
2805 be147d08 j_mayer
    rd = rD(ctx->opcode);
2806 be147d08 j_mayer
    if (unlikely((rd & 1) || rd == ra)) {
2807 be147d08 j_mayer
        GEN_EXCP_INVAL(ctx);
2808 be147d08 j_mayer
        return;
2809 be147d08 j_mayer
    }
2810 76db3ba4 aurel32
    if (unlikely(ctx->le_mode)) {
2811 be147d08 j_mayer
        /* Little-endian mode is not handled */
2812 be147d08 j_mayer
        GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2813 be147d08 j_mayer
        return;
2814 be147d08 j_mayer
    }
2815 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);
2816 a7812ae4 pbrook
    EA = tcg_temp_new();
2817 76db3ba4 aurel32
    gen_addr_imm_index(ctx, EA, 0x0F);
2818 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2819 76db3ba4 aurel32
    gen_addr_add(ctx, EA, EA, 8);
2820 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
2821 b61f2753 aurel32
    tcg_temp_free(EA);
2822 be147d08 j_mayer
#endif
2823 be147d08 j_mayer
}
2824 d9bce9d9 j_mayer
#endif
2825 79aceca5 bellard
2826 79aceca5 bellard
/***                              Integer store                            ***/
2827 0c8aacd4 aurel32
#define GEN_ST(name, stop, opc, type)                                         \
2828 0c8aacd4 aurel32
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
2829 79aceca5 bellard
{                                                                             \
2830 76db3ba4 aurel32
    TCGv EA;                                                                  \
2831 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2832 76db3ba4 aurel32
    EA = tcg_temp_new();                                                      \
2833 76db3ba4 aurel32
    gen_addr_imm_index(ctx, EA, 0);                                           \
2834 76db3ba4 aurel32
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2835 b61f2753 aurel32
    tcg_temp_free(EA);                                                        \
2836 79aceca5 bellard
}
2837 79aceca5 bellard
2838 0c8aacd4 aurel32
#define GEN_STU(name, stop, opc, type)                                        \
2839 0c8aacd4 aurel32
GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
2840 79aceca5 bellard
{                                                                             \
2841 b61f2753 aurel32
    TCGv EA;                                                                  \
2842 76a66253 j_mayer
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2843 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);                                                  \
2844 9fddaa0c bellard
        return;                                                               \
2845 9a64fbe4 bellard
    }                                                                         \
2846 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2847 0c8aacd4 aurel32
    EA = tcg_temp_new();                                                      \
2848 9d53c753 j_mayer
    if (type == PPC_64B)                                                      \
2849 76db3ba4 aurel32
        gen_addr_imm_index(ctx, EA, 0x03);                                    \
2850 9d53c753 j_mayer
    else                                                                      \
2851 76db3ba4 aurel32
        gen_addr_imm_index(ctx, EA, 0);                                       \
2852 76db3ba4 aurel32
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2853 b61f2753 aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2854 b61f2753 aurel32
    tcg_temp_free(EA);                                                        \
2855 79aceca5 bellard
}
2856 79aceca5 bellard
2857 0c8aacd4 aurel32
#define GEN_STUX(name, stop, opc2, opc3, type)                                \
2858 0c8aacd4 aurel32
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type)                     \
2859 79aceca5 bellard
{                                                                             \
2860 b61f2753 aurel32
    TCGv EA;                                                                  \
2861 76a66253 j_mayer
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
2862 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);                                                  \
2863 9fddaa0c bellard
        return;                                                               \
2864 9a64fbe4 bellard
    }                                                                         \
2865 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2866 0c8aacd4 aurel32
    EA = tcg_temp_new();                                                      \
2867 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
2868 76db3ba4 aurel32
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2869 b61f2753 aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
2870 b61f2753 aurel32
    tcg_temp_free(EA);                                                        \
2871 79aceca5 bellard
}
2872 79aceca5 bellard
2873 0c8aacd4 aurel32
#define GEN_STX(name, stop, opc2, opc3, type)                                 \
2874 0c8aacd4 aurel32
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
2875 79aceca5 bellard
{                                                                             \
2876 76db3ba4 aurel32
    TCGv EA;                                                                  \
2877 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
2878 76db3ba4 aurel32
    EA = tcg_temp_new();                                                      \
2879 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
2880 76db3ba4 aurel32
    gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);                       \
2881 b61f2753 aurel32
    tcg_temp_free(EA);                                                        \
2882 79aceca5 bellard
}
2883 79aceca5 bellard
2884 0c8aacd4 aurel32
#define GEN_STS(name, stop, op, type)                                         \
2885 0c8aacd4 aurel32
GEN_ST(name, stop, op | 0x20, type);                                          \
2886 0c8aacd4 aurel32
GEN_STU(name, stop, op | 0x21, type);                                         \
2887 0c8aacd4 aurel32
GEN_STUX(name, stop, 0x17, op | 0x01, type);                                  \
2888 0c8aacd4 aurel32
GEN_STX(name, stop, 0x17, op | 0x00, type)
2889 79aceca5 bellard
2890 79aceca5 bellard
/* stb stbu stbux stbx */
2891 0c8aacd4 aurel32
GEN_STS(stb, st8, 0x06, PPC_INTEGER);
2892 79aceca5 bellard
/* sth sthu sthux sthx */
2893 0c8aacd4 aurel32
GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
2894 79aceca5 bellard
/* stw stwu stwux stwx */
2895 0c8aacd4 aurel32
GEN_STS(stw, st32, 0x04, PPC_INTEGER);
2896 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
2897 0c8aacd4 aurel32
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
2898 0c8aacd4 aurel32
GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
2899 be147d08 j_mayer
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2900 d9bce9d9 j_mayer
{
2901 be147d08 j_mayer
    int rs;
2902 b61f2753 aurel32
    TCGv EA;
2903 be147d08 j_mayer
2904 be147d08 j_mayer
    rs = rS(ctx->opcode);
2905 be147d08 j_mayer
    if ((ctx->opcode & 0x3) == 0x2) {
2906 be147d08 j_mayer
#if defined(CONFIG_USER_ONLY)
2907 be147d08 j_mayer
        GEN_EXCP_PRIVOPC(ctx);
2908 be147d08 j_mayer
#else
2909 be147d08 j_mayer
        /* stq */
2910 76db3ba4 aurel32
        if (unlikely(ctx->mem_idx == 0)) {
2911 be147d08 j_mayer
            GEN_EXCP_PRIVOPC(ctx);
2912 be147d08 j_mayer
            return;
2913 be147d08 j_mayer
        }
2914 be147d08 j_mayer
        if (unlikely(rs & 1)) {
2915 e1833e1f j_mayer
            GEN_EXCP_INVAL(ctx);
2916 d9bce9d9 j_mayer
            return;
2917 d9bce9d9 j_mayer
        }
2918 76db3ba4 aurel32
        if (unlikely(ctx->le_mode)) {
2919 be147d08 j_mayer
            /* Little-endian mode is not handled */
2920 be147d08 j_mayer
            GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2921 be147d08 j_mayer
            return;
2922 be147d08 j_mayer
        }
2923 76db3ba4 aurel32
        gen_set_access_type(ctx, ACCESS_INT);
2924 a7812ae4 pbrook
        EA = tcg_temp_new();
2925 76db3ba4 aurel32
        gen_addr_imm_index(ctx, EA, 0x03);
2926 76db3ba4 aurel32
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2927 76db3ba4 aurel32
        gen_addr_add(ctx, EA, EA, 8);
2928 76db3ba4 aurel32
        gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
2929 b61f2753 aurel32
        tcg_temp_free(EA);
2930 be147d08 j_mayer
#endif
2931 be147d08 j_mayer
    } else {
2932 be147d08 j_mayer
        /* std / stdu */
2933 be147d08 j_mayer
        if (Rc(ctx->opcode)) {
2934 be147d08 j_mayer
            if (unlikely(rA(ctx->opcode) == 0)) {
2935 be147d08 j_mayer
                GEN_EXCP_INVAL(ctx);
2936 be147d08 j_mayer
                return;
2937 be147d08 j_mayer
            }
2938 be147d08 j_mayer
        }
2939 76db3ba4 aurel32
        gen_set_access_type(ctx, ACCESS_INT);
2940 a7812ae4 pbrook
        EA = tcg_temp_new();
2941 76db3ba4 aurel32
        gen_addr_imm_index(ctx, EA, 0x03);
2942 76db3ba4 aurel32
        gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2943 be147d08 j_mayer
        if (Rc(ctx->opcode))
2944 b61f2753 aurel32
            tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2945 b61f2753 aurel32
        tcg_temp_free(EA);
2946 d9bce9d9 j_mayer
    }
2947 d9bce9d9 j_mayer
}
2948 d9bce9d9 j_mayer
#endif
2949 79aceca5 bellard
/***                Integer load and store with byte reverse               ***/
2950 79aceca5 bellard
/* lhbrx */
2951 76db3ba4 aurel32
static void always_inline gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
2952 b61f2753 aurel32
{
2953 76db3ba4 aurel32
    tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2954 76db3ba4 aurel32
    if (likely(!ctx->le_mode)) {
2955 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2956 76db3ba4 aurel32
        TCGv_i32 t0 = tcg_temp_new_i32();
2957 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
2958 76db3ba4 aurel32
        tcg_gen_bswap16_i32(t0, t0);
2959 76db3ba4 aurel32
        tcg_gen_extu_i32_tl(arg1, t0);
2960 76db3ba4 aurel32
        tcg_temp_free_i32(t0);
2961 76db3ba4 aurel32
#else
2962 76db3ba4 aurel32
        tcg_gen_bswap16_i32(arg1, arg1);
2963 76db3ba4 aurel32
#endif
2964 76db3ba4 aurel32
    }
2965 b61f2753 aurel32
}
2966 0c8aacd4 aurel32
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
2967 b61f2753 aurel32
2968 79aceca5 bellard
/* lwbrx */
2969 76db3ba4 aurel32
static void always_inline gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
2970 b61f2753 aurel32
{
2971 76db3ba4 aurel32
    tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2972 76db3ba4 aurel32
    if (likely(!ctx->le_mode)) {
2973 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2974 76db3ba4 aurel32
        TCGv_i32 t0 = tcg_temp_new_i32();
2975 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
2976 76db3ba4 aurel32
        tcg_gen_bswap_i32(t0, t0);
2977 76db3ba4 aurel32
        tcg_gen_extu_i32_tl(arg1, t0);
2978 76db3ba4 aurel32
        tcg_temp_free_i32(t0);
2979 76db3ba4 aurel32
#else
2980 76db3ba4 aurel32
        tcg_gen_bswap_i32(arg1, arg1);
2981 76db3ba4 aurel32
#endif
2982 76db3ba4 aurel32
    }
2983 b61f2753 aurel32
}
2984 0c8aacd4 aurel32
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
2985 b61f2753 aurel32
2986 79aceca5 bellard
/* sthbrx */
2987 76db3ba4 aurel32
static void always_inline gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
2988 b61f2753 aurel32
{
2989 76db3ba4 aurel32
    if (likely(!ctx->le_mode)) {
2990 76db3ba4 aurel32
#if defined(TARGET_PPC64)
2991 76db3ba4 aurel32
        TCGv_i32 t0;
2992 76db3ba4 aurel32
        TCGv t1;
2993 76db3ba4 aurel32
        t0 = tcg_temp_new_i32();
2994 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
2995 76db3ba4 aurel32
        tcg_gen_ext16u_i32(t0, t0);
2996 76db3ba4 aurel32
        tcg_gen_bswap16_i32(t0, t0);
2997 76db3ba4 aurel32
        t1 = tcg_temp_new();
2998 76db3ba4 aurel32
        tcg_gen_extu_i32_tl(t1, t0);
2999 76db3ba4 aurel32
        tcg_temp_free_i32(t0);
3000 76db3ba4 aurel32
        tcg_gen_qemu_st16(t1, arg2, ctx->mem_idx);
3001 76db3ba4 aurel32
        tcg_temp_free(t1);
3002 76db3ba4 aurel32
#else
3003 76db3ba4 aurel32
        TCGv t0 = tcg_temp_new();
3004 76db3ba4 aurel32
        tcg_gen_ext16u_tl(t0, arg1);
3005 76db3ba4 aurel32
        tcg_gen_bswap16_i32(t0, t0);
3006 76db3ba4 aurel32
        tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
3007 76db3ba4 aurel32
        tcg_temp_free(t0);
3008 76db3ba4 aurel32
#endif
3009 76db3ba4 aurel32
    } else {
3010 76db3ba4 aurel32
        tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
3011 76db3ba4 aurel32
    }
3012 b61f2753 aurel32
}
3013 0c8aacd4 aurel32
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
3014 b61f2753 aurel32
3015 79aceca5 bellard
/* stwbrx */
3016 76db3ba4 aurel32
static void always_inline gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
3017 b61f2753 aurel32
{
3018 76db3ba4 aurel32
    if (likely(!ctx->le_mode)) {
3019 76db3ba4 aurel32
#if defined(TARGET_PPC64)
3020 76db3ba4 aurel32
        TCGv_i32 t0;
3021 76db3ba4 aurel32
        TCGv t1;
3022 76db3ba4 aurel32
        t0 = tcg_temp_new_i32();
3023 76db3ba4 aurel32
        tcg_gen_trunc_tl_i32(t0, arg1);
3024 76db3ba4 aurel32
        tcg_gen_bswap_i32(t0, t0);
3025 76db3ba4 aurel32
        t1 = tcg_temp_new();
3026 76db3ba4 aurel32
        tcg_gen_extu_i32_tl(t1, t0);
3027 76db3ba4 aurel32
        tcg_temp_free_i32(t0);
3028 76db3ba4 aurel32
        tcg_gen_qemu_st32(t1, arg2, ctx->mem_idx);
3029 76db3ba4 aurel32
        tcg_temp_free(t1);
3030 76db3ba4 aurel32
#else
3031 76db3ba4 aurel32
        TCGv t0 = tcg_temp_new_i32();
3032 76db3ba4 aurel32
        tcg_gen_bswap_i32(t0, arg1);
3033 76db3ba4 aurel32
        tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
3034 76db3ba4 aurel32
        tcg_temp_free(t0);
3035 76db3ba4 aurel32
#endif
3036 76db3ba4 aurel32
    } else {
3037 76db3ba4 aurel32
        tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
3038 76db3ba4 aurel32
    }
3039 b61f2753 aurel32
}
3040 0c8aacd4 aurel32
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
3041 79aceca5 bellard
3042 79aceca5 bellard
/***                    Integer load and store multiple                    ***/
3043 79aceca5 bellard
/* lmw */
3044 79aceca5 bellard
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
3045 79aceca5 bellard
{
3046 76db3ba4 aurel32
    TCGv t0;
3047 76db3ba4 aurel32
    TCGv_i32 t1;
3048 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);
3049 76a66253 j_mayer
    /* NIP cannot be restored if the memory exception comes from an helper */
3050 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip - 4);
3051 76db3ba4 aurel32
    t0 = tcg_temp_new();
3052 76db3ba4 aurel32
    t1 = tcg_const_i32(rD(ctx->opcode));
3053 76db3ba4 aurel32
    gen_addr_imm_index(ctx, t0, 0);
3054 ff4a62cd aurel32
    gen_helper_lmw(t0, t1);
3055 ff4a62cd aurel32
    tcg_temp_free(t0);
3056 ff4a62cd aurel32
    tcg_temp_free_i32(t1);
3057 79aceca5 bellard
}
3058 79aceca5 bellard
3059 79aceca5 bellard
/* stmw */
3060 79aceca5 bellard
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
3061 79aceca5 bellard
{
3062 76db3ba4 aurel32
    TCGv t0;
3063 76db3ba4 aurel32
    TCGv_i32 t1;
3064 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);
3065 76a66253 j_mayer
    /* NIP cannot be restored if the memory exception comes from an helper */
3066 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip - 4);
3067 76db3ba4 aurel32
    t0 = tcg_temp_new();
3068 76db3ba4 aurel32
    t1 = tcg_const_i32(rS(ctx->opcode));
3069 76db3ba4 aurel32
    gen_addr_imm_index(ctx, t0, 0);
3070 ff4a62cd aurel32
    gen_helper_stmw(t0, t1);
3071 ff4a62cd aurel32
    tcg_temp_free(t0);
3072 ff4a62cd aurel32
    tcg_temp_free_i32(t1);
3073 79aceca5 bellard
}
3074 79aceca5 bellard
3075 79aceca5 bellard
/***                    Integer load and store strings                     ***/
3076 79aceca5 bellard
/* lswi */
3077 3fc6c082 bellard
/* PowerPC32 specification says we must generate an exception if
3078 9a64fbe4 bellard
 * rA is in the range of registers to be loaded.
3079 9a64fbe4 bellard
 * In an other hand, IBM says this is valid, but rA won't be loaded.
3080 9a64fbe4 bellard
 * For now, I'll follow the spec...
3081 9a64fbe4 bellard
 */
3082 05332d70 j_mayer
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
3083 79aceca5 bellard
{
3084 dfbc799d aurel32
    TCGv t0;
3085 dfbc799d aurel32
    TCGv_i32 t1, t2;
3086 79aceca5 bellard
    int nb = NB(ctx->opcode);
3087 79aceca5 bellard
    int start = rD(ctx->opcode);
3088 9a64fbe4 bellard
    int ra = rA(ctx->opcode);
3089 79aceca5 bellard
    int nr;
3090 79aceca5 bellard
3091 79aceca5 bellard
    if (nb == 0)
3092 79aceca5 bellard
        nb = 32;
3093 79aceca5 bellard
    nr = nb / 4;
3094 76a66253 j_mayer
    if (unlikely(((start + nr) > 32  &&
3095 76a66253 j_mayer
                  start <= ra && (start + nr - 32) > ra) ||
3096 76a66253 j_mayer
                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
3097 e1833e1f j_mayer
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3098 e1833e1f j_mayer
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
3099 9fddaa0c bellard
        return;
3100 297d8e62 bellard
    }
3101 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);
3102 8dd4983c bellard
    /* NIP cannot be restored if the memory exception comes from an helper */
3103 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip - 4);
3104 dfbc799d aurel32
    t0 = tcg_temp_new();
3105 76db3ba4 aurel32
    gen_addr_register(ctx, t0);
3106 dfbc799d aurel32
    t1 = tcg_const_i32(nb);
3107 dfbc799d aurel32
    t2 = tcg_const_i32(start);
3108 dfbc799d aurel32
    gen_helper_lsw(t0, t1, t2);
3109 dfbc799d aurel32
    tcg_temp_free(t0);
3110 dfbc799d aurel32
    tcg_temp_free_i32(t1);
3111 dfbc799d aurel32
    tcg_temp_free_i32(t2);
3112 79aceca5 bellard
}
3113 79aceca5 bellard
3114 79aceca5 bellard
/* lswx */
3115 05332d70 j_mayer
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
3116 79aceca5 bellard
{
3117 76db3ba4 aurel32
    TCGv t0;
3118 76db3ba4 aurel32
    TCGv_i32 t1, t2, t3;
3119 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);
3120 76a66253 j_mayer
    /* NIP cannot be restored if the memory exception comes from an helper */
3121 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip - 4);
3122 76db3ba4 aurel32
    t0 = tcg_temp_new();
3123 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
3124 76db3ba4 aurel32
    t1 = tcg_const_i32(rD(ctx->opcode));
3125 76db3ba4 aurel32
    t2 = tcg_const_i32(rA(ctx->opcode));
3126 76db3ba4 aurel32
    t3 = tcg_const_i32(rB(ctx->opcode));
3127 dfbc799d aurel32
    gen_helper_lswx(t0, t1, t2, t3);
3128 dfbc799d aurel32
    tcg_temp_free(t0);
3129 dfbc799d aurel32
    tcg_temp_free_i32(t1);
3130 dfbc799d aurel32
    tcg_temp_free_i32(t2);
3131 dfbc799d aurel32
    tcg_temp_free_i32(t3);
3132 79aceca5 bellard
}
3133 79aceca5 bellard
3134 79aceca5 bellard
/* stswi */
3135 05332d70 j_mayer
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
3136 79aceca5 bellard
{
3137 76db3ba4 aurel32
    TCGv t0;
3138 76db3ba4 aurel32
    TCGv_i32 t1, t2;
3139 4b3686fa bellard
    int nb = NB(ctx->opcode);
3140 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);
3141 76a66253 j_mayer
    /* NIP cannot be restored if the memory exception comes from an helper */
3142 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip - 4);
3143 76db3ba4 aurel32
    t0 = tcg_temp_new();
3144 76db3ba4 aurel32
    gen_addr_register(ctx, t0);
3145 4b3686fa bellard
    if (nb == 0)
3146 4b3686fa bellard
        nb = 32;
3147 dfbc799d aurel32
    t1 = tcg_const_i32(nb);
3148 76db3ba4 aurel32
    t2 = tcg_const_i32(rS(ctx->opcode));
3149 dfbc799d aurel32
    gen_helper_stsw(t0, t1, t2);
3150 dfbc799d aurel32
    tcg_temp_free(t0);
3151 dfbc799d aurel32
    tcg_temp_free_i32(t1);
3152 dfbc799d aurel32
    tcg_temp_free_i32(t2);
3153 79aceca5 bellard
}
3154 79aceca5 bellard
3155 79aceca5 bellard
/* stswx */
3156 05332d70 j_mayer
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
3157 79aceca5 bellard
{
3158 76db3ba4 aurel32
    TCGv t0;
3159 76db3ba4 aurel32
    TCGv_i32 t1, t2;
3160 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);
3161 8dd4983c bellard
    /* NIP cannot be restored if the memory exception comes from an helper */
3162 5fafdf24 ths
    gen_update_nip(ctx, ctx->nip - 4);
3163 76db3ba4 aurel32
    t0 = tcg_temp_new();
3164 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
3165 76db3ba4 aurel32
    t1 = tcg_temp_new_i32();
3166 dfbc799d aurel32
    tcg_gen_trunc_tl_i32(t1, cpu_xer);
3167 dfbc799d aurel32
    tcg_gen_andi_i32(t1, t1, 0x7F);
3168 76db3ba4 aurel32
    t2 = tcg_const_i32(rS(ctx->opcode));
3169 dfbc799d aurel32
    gen_helper_stsw(t0, t1, t2);
3170 dfbc799d aurel32
    tcg_temp_free(t0);
3171 dfbc799d aurel32
    tcg_temp_free_i32(t1);
3172 dfbc799d aurel32
    tcg_temp_free_i32(t2);
3173 79aceca5 bellard
}
3174 79aceca5 bellard
3175 79aceca5 bellard
/***                        Memory synchronisation                         ***/
3176 79aceca5 bellard
/* eieio */
3177 0db1b20e j_mayer
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
3178 79aceca5 bellard
{
3179 79aceca5 bellard
}
3180 79aceca5 bellard
3181 79aceca5 bellard
/* isync */
3182 0db1b20e j_mayer
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
3183 79aceca5 bellard
{
3184 e1833e1f j_mayer
    GEN_STOP(ctx);
3185 79aceca5 bellard
}
3186 79aceca5 bellard
3187 111bfab3 bellard
/* lwarx */
3188 76a66253 j_mayer
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
3189 79aceca5 bellard
{
3190 76db3ba4 aurel32
    TCGv t0;
3191 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_RES);
3192 76db3ba4 aurel32
    t0 = tcg_temp_local_new();
3193 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
3194 cf360a32 aurel32
    gen_check_align(ctx, t0, 0x03);
3195 76db3ba4 aurel32
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
3196 cf360a32 aurel32
    tcg_gen_mov_tl(cpu_reserve, t0);
3197 cf360a32 aurel32
    tcg_temp_free(t0);
3198 79aceca5 bellard
}
3199 79aceca5 bellard
3200 79aceca5 bellard
/* stwcx. */
3201 c7697e1f j_mayer
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
3202 79aceca5 bellard
{
3203 76db3ba4 aurel32
    int l1;
3204 76db3ba4 aurel32
    TCGv t0;
3205 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_RES);
3206 76db3ba4 aurel32
    t0 = tcg_temp_local_new();
3207 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
3208 cf360a32 aurel32
    gen_check_align(ctx, t0, 0x03);
3209 cf360a32 aurel32
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3210 cf360a32 aurel32
    tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3211 cf360a32 aurel32
    tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3212 76db3ba4 aurel32
    l1 = gen_new_label();
3213 cf360a32 aurel32
    tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3214 cf360a32 aurel32
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3215 76db3ba4 aurel32
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3216 cf360a32 aurel32
    gen_set_label(l1);
3217 cf360a32 aurel32
    tcg_gen_movi_tl(cpu_reserve, -1);
3218 cf360a32 aurel32
    tcg_temp_free(t0);
3219 79aceca5 bellard
}
3220 79aceca5 bellard
3221 426613db j_mayer
#if defined(TARGET_PPC64)
3222 426613db j_mayer
/* ldarx */
3223 a750fc0b j_mayer
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
3224 426613db j_mayer
{
3225 76db3ba4 aurel32
    TCGv t0;
3226 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_RES);
3227 76db3ba4 aurel32
    t0 = tcg_temp_local_new();
3228 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
3229 cf360a32 aurel32
    gen_check_align(ctx, t0, 0x07);
3230 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], t0);
3231 cf360a32 aurel32
    tcg_gen_mov_tl(cpu_reserve, t0);
3232 cf360a32 aurel32
    tcg_temp_free(t0);
3233 426613db j_mayer
}
3234 426613db j_mayer
3235 426613db j_mayer
/* stdcx. */
3236 c7697e1f j_mayer
GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
3237 426613db j_mayer
{
3238 76db3ba4 aurel32
    int l1;
3239 76db3ba4 aurel32
    TCGv t0;
3240 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_RES);
3241 76db3ba4 aurel32
    t0 = tcg_temp_local_new();
3242 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
3243 cf360a32 aurel32
    gen_check_align(ctx, t0, 0x07);
3244 cf360a32 aurel32
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3245 cf360a32 aurel32
    tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3246 cf360a32 aurel32
    tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3247 76db3ba4 aurel32
    l1 = gen_new_label();
3248 cf360a32 aurel32
    tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3249 cf360a32 aurel32
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3250 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3251 cf360a32 aurel32
    gen_set_label(l1);
3252 cf360a32 aurel32
    tcg_gen_movi_tl(cpu_reserve, -1);
3253 cf360a32 aurel32
    tcg_temp_free(t0);
3254 426613db j_mayer
}
3255 426613db j_mayer
#endif /* defined(TARGET_PPC64) */
3256 426613db j_mayer
3257 79aceca5 bellard
/* sync */
3258 a902d886 j_mayer
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
3259 79aceca5 bellard
{
3260 79aceca5 bellard
}
3261 79aceca5 bellard
3262 0db1b20e j_mayer
/* wait */
3263 0db1b20e j_mayer
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
3264 0db1b20e j_mayer
{
3265 931ff272 aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();
3266 931ff272 aurel32
    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
3267 931ff272 aurel32
    tcg_temp_free_i32(t0);
3268 0db1b20e j_mayer
    /* Stop translation, as the CPU is supposed to sleep from now */
3269 be147d08 j_mayer
    GEN_EXCP(ctx, EXCP_HLT, 1);
3270 0db1b20e j_mayer
}
3271 0db1b20e j_mayer
3272 79aceca5 bellard
/***                         Floating-point load                           ***/
3273 a0d7d5a7 aurel32
#define GEN_LDF(name, ldop, opc, type)                                        \
3274 a0d7d5a7 aurel32
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
3275 79aceca5 bellard
{                                                                             \
3276 a0d7d5a7 aurel32
    TCGv EA;                                                                  \
3277 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3278 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
3279 4ecc3190 bellard
        return;                                                               \
3280 4ecc3190 bellard
    }                                                                         \
3281 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3282 a0d7d5a7 aurel32
    EA = tcg_temp_new();                                                      \
3283 76db3ba4 aurel32
    gen_addr_imm_index(ctx, EA, 0);                                           \
3284 76db3ba4 aurel32
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3285 a0d7d5a7 aurel32
    tcg_temp_free(EA);                                                        \
3286 79aceca5 bellard
}
3287 79aceca5 bellard
3288 a0d7d5a7 aurel32
#define GEN_LDUF(name, ldop, opc, type)                                       \
3289 a0d7d5a7 aurel32
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
3290 79aceca5 bellard
{                                                                             \
3291 a0d7d5a7 aurel32
    TCGv EA;                                                                  \
3292 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3293 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
3294 4ecc3190 bellard
        return;                                                               \
3295 4ecc3190 bellard
    }                                                                         \
3296 76a66253 j_mayer
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3297 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);                                                  \
3298 9fddaa0c bellard
        return;                                                               \
3299 9a64fbe4 bellard
    }                                                                         \
3300 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3301 a0d7d5a7 aurel32
    EA = tcg_temp_new();                                                      \
3302 76db3ba4 aurel32
    gen_addr_imm_index(ctx, EA, 0);                                           \
3303 76db3ba4 aurel32
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3304 a0d7d5a7 aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3305 a0d7d5a7 aurel32
    tcg_temp_free(EA);                                                        \
3306 79aceca5 bellard
}
3307 79aceca5 bellard
3308 a0d7d5a7 aurel32
#define GEN_LDUXF(name, ldop, opc, type)                                      \
3309 a0d7d5a7 aurel32
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type)                      \
3310 79aceca5 bellard
{                                                                             \
3311 a0d7d5a7 aurel32
    TCGv EA;                                                                  \
3312 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3313 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
3314 4ecc3190 bellard
        return;                                                               \
3315 4ecc3190 bellard
    }                                                                         \
3316 76a66253 j_mayer
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3317 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);                                                  \
3318 9fddaa0c bellard
        return;                                                               \
3319 9a64fbe4 bellard
    }                                                                         \
3320 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3321 a0d7d5a7 aurel32
    EA = tcg_temp_new();                                                      \
3322 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
3323 76db3ba4 aurel32
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3324 a0d7d5a7 aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3325 a0d7d5a7 aurel32
    tcg_temp_free(EA);                                                        \
3326 79aceca5 bellard
}
3327 79aceca5 bellard
3328 a0d7d5a7 aurel32
#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
3329 a0d7d5a7 aurel32
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
3330 79aceca5 bellard
{                                                                             \
3331 a0d7d5a7 aurel32
    TCGv EA;                                                                  \
3332 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3333 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
3334 4ecc3190 bellard
        return;                                                               \
3335 4ecc3190 bellard
    }                                                                         \
3336 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3337 a0d7d5a7 aurel32
    EA = tcg_temp_new();                                                      \
3338 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
3339 76db3ba4 aurel32
    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
3340 a0d7d5a7 aurel32
    tcg_temp_free(EA);                                                        \
3341 79aceca5 bellard
}
3342 79aceca5 bellard
3343 a0d7d5a7 aurel32
#define GEN_LDFS(name, ldop, op, type)                                        \
3344 a0d7d5a7 aurel32
GEN_LDF(name, ldop, op | 0x20, type);                                         \
3345 a0d7d5a7 aurel32
GEN_LDUF(name, ldop, op | 0x21, type);                                        \
3346 a0d7d5a7 aurel32
GEN_LDUXF(name, ldop, op | 0x01, type);                                       \
3347 a0d7d5a7 aurel32
GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3348 a0d7d5a7 aurel32
3349 76db3ba4 aurel32
static always_inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3350 a0d7d5a7 aurel32
{
3351 a0d7d5a7 aurel32
    TCGv t0 = tcg_temp_new();
3352 a0d7d5a7 aurel32
    TCGv_i32 t1 = tcg_temp_new_i32();
3353 76db3ba4 aurel32
    gen_qemu_ld32u(ctx, t0, arg2);
3354 a0d7d5a7 aurel32
    tcg_gen_trunc_tl_i32(t1, t0);
3355 a0d7d5a7 aurel32
    tcg_temp_free(t0);
3356 a0d7d5a7 aurel32
    gen_helper_float32_to_float64(arg1, t1);
3357 a0d7d5a7 aurel32
    tcg_temp_free_i32(t1);
3358 a0d7d5a7 aurel32
}
3359 79aceca5 bellard
3360 a0d7d5a7 aurel32
 /* lfd lfdu lfdux lfdx */
3361 a0d7d5a7 aurel32
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3362 a0d7d5a7 aurel32
 /* lfs lfsu lfsux lfsx */
3363 a0d7d5a7 aurel32
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
3364 79aceca5 bellard
3365 79aceca5 bellard
/***                         Floating-point store                          ***/
3366 a0d7d5a7 aurel32
#define GEN_STF(name, stop, opc, type)                                        \
3367 a0d7d5a7 aurel32
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type)                          \
3368 79aceca5 bellard
{                                                                             \
3369 a0d7d5a7 aurel32
    TCGv EA;                                                                  \
3370 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3371 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
3372 4ecc3190 bellard
        return;                                                               \
3373 4ecc3190 bellard
    }                                                                         \
3374 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3375 a0d7d5a7 aurel32
    EA = tcg_temp_new();                                                      \
3376 76db3ba4 aurel32
    gen_addr_imm_index(ctx, EA, 0);                                           \
3377 76db3ba4 aurel32
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3378 a0d7d5a7 aurel32
    tcg_temp_free(EA);                                                        \
3379 79aceca5 bellard
}
3380 79aceca5 bellard
3381 a0d7d5a7 aurel32
#define GEN_STUF(name, stop, opc, type)                                       \
3382 a0d7d5a7 aurel32
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type)                       \
3383 79aceca5 bellard
{                                                                             \
3384 a0d7d5a7 aurel32
    TCGv EA;                                                                  \
3385 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3386 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
3387 4ecc3190 bellard
        return;                                                               \
3388 4ecc3190 bellard
    }                                                                         \
3389 76a66253 j_mayer
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3390 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);                                                  \
3391 9fddaa0c bellard
        return;                                                               \
3392 9a64fbe4 bellard
    }                                                                         \
3393 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3394 a0d7d5a7 aurel32
    EA = tcg_temp_new();                                                      \
3395 76db3ba4 aurel32
    gen_addr_imm_index(ctx, EA, 0);                                           \
3396 76db3ba4 aurel32
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3397 a0d7d5a7 aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3398 a0d7d5a7 aurel32
    tcg_temp_free(EA);                                                        \
3399 79aceca5 bellard
}
3400 79aceca5 bellard
3401 a0d7d5a7 aurel32
#define GEN_STUXF(name, stop, opc, type)                                      \
3402 a0d7d5a7 aurel32
GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type)                      \
3403 79aceca5 bellard
{                                                                             \
3404 a0d7d5a7 aurel32
    TCGv EA;                                                                  \
3405 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3406 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
3407 4ecc3190 bellard
        return;                                                               \
3408 4ecc3190 bellard
    }                                                                         \
3409 76a66253 j_mayer
    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
3410 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);                                                  \
3411 9fddaa0c bellard
        return;                                                               \
3412 9a64fbe4 bellard
    }                                                                         \
3413 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3414 a0d7d5a7 aurel32
    EA = tcg_temp_new();                                                      \
3415 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
3416 76db3ba4 aurel32
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3417 a0d7d5a7 aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
3418 a0d7d5a7 aurel32
    tcg_temp_free(EA);                                                        \
3419 79aceca5 bellard
}
3420 79aceca5 bellard
3421 a0d7d5a7 aurel32
#define GEN_STXF(name, stop, opc2, opc3, type)                                \
3422 a0d7d5a7 aurel32
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type)                      \
3423 79aceca5 bellard
{                                                                             \
3424 a0d7d5a7 aurel32
    TCGv EA;                                                                  \
3425 76a66253 j_mayer
    if (unlikely(!ctx->fpu_enabled)) {                                        \
3426 e1833e1f j_mayer
        GEN_EXCP_NO_FP(ctx);                                                  \
3427 4ecc3190 bellard
        return;                                                               \
3428 4ecc3190 bellard
    }                                                                         \
3429 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
3430 a0d7d5a7 aurel32
    EA = tcg_temp_new();                                                      \
3431 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
3432 76db3ba4 aurel32
    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
3433 a0d7d5a7 aurel32
    tcg_temp_free(EA);                                                        \
3434 79aceca5 bellard
}
3435 79aceca5 bellard
3436 a0d7d5a7 aurel32
#define GEN_STFS(name, stop, op, type)                                        \
3437 a0d7d5a7 aurel32
GEN_STF(name, stop, op | 0x20, type);                                         \
3438 a0d7d5a7 aurel32
GEN_STUF(name, stop, op | 0x21, type);                                        \
3439 a0d7d5a7 aurel32
GEN_STUXF(name, stop, op | 0x01, type);                                       \
3440 a0d7d5a7 aurel32
GEN_STXF(name, stop, 0x17, op | 0x00, type)
3441 a0d7d5a7 aurel32
3442 76db3ba4 aurel32
static always_inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3443 a0d7d5a7 aurel32
{
3444 a0d7d5a7 aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();
3445 a0d7d5a7 aurel32
    TCGv t1 = tcg_temp_new();
3446 a0d7d5a7 aurel32
    gen_helper_float64_to_float32(t0, arg1);
3447 a0d7d5a7 aurel32
    tcg_gen_extu_i32_tl(t1, t0);
3448 a0d7d5a7 aurel32
    tcg_temp_free_i32(t0);
3449 76db3ba4 aurel32
    gen_qemu_st32(ctx, t1, arg2);
3450 a0d7d5a7 aurel32
    tcg_temp_free(t1);
3451 a0d7d5a7 aurel32
}
3452 79aceca5 bellard
3453 79aceca5 bellard
/* stfd stfdu stfdux stfdx */
3454 a0d7d5a7 aurel32
GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
3455 79aceca5 bellard
/* stfs stfsu stfsux stfsx */
3456 a0d7d5a7 aurel32
GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
3457 79aceca5 bellard
3458 79aceca5 bellard
/* Optional: */
3459 76db3ba4 aurel32
static always_inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
3460 a0d7d5a7 aurel32
{
3461 a0d7d5a7 aurel32
    TCGv t0 = tcg_temp_new();
3462 a0d7d5a7 aurel32
    tcg_gen_trunc_i64_tl(t0, arg1),
3463 76db3ba4 aurel32
    gen_qemu_st32(ctx, t0, arg2);
3464 a0d7d5a7 aurel32
    tcg_temp_free(t0);
3465 a0d7d5a7 aurel32
}
3466 79aceca5 bellard
/* stfiwx */
3467 a0d7d5a7 aurel32
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
3468 79aceca5 bellard
3469 79aceca5 bellard
/***                                Branch                                 ***/
3470 b068d6a7 j_mayer
static always_inline void gen_goto_tb (DisasContext *ctx, int n,
3471 b068d6a7 j_mayer
                                       target_ulong dest)
3472 c1942362 bellard
{
3473 c1942362 bellard
    TranslationBlock *tb;
3474 c1942362 bellard
    tb = ctx->tb;
3475 a2ffb812 aurel32
#if defined(TARGET_PPC64)
3476 a2ffb812 aurel32
    if (!ctx->sf_mode)
3477 a2ffb812 aurel32
        dest = (uint32_t) dest;
3478 a2ffb812 aurel32
#endif
3479 57fec1fe bellard
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3480 8cbcb4fa aurel32
        likely(!ctx->singlestep_enabled)) {
3481 57fec1fe bellard
        tcg_gen_goto_tb(n);
3482 a2ffb812 aurel32
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3483 57fec1fe bellard
        tcg_gen_exit_tb((long)tb + n);
3484 c1942362 bellard
    } else {
3485 a2ffb812 aurel32
        tcg_gen_movi_tl(cpu_nip, dest & ~3);
3486 8cbcb4fa aurel32
        if (unlikely(ctx->singlestep_enabled)) {
3487 8cbcb4fa aurel32
            if ((ctx->singlestep_enabled &
3488 bdc4e053 aurel32
                (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
3489 8cbcb4fa aurel32
                ctx->exception == POWERPC_EXCP_BRANCH) {
3490 8cbcb4fa aurel32
                target_ulong tmp = ctx->nip;
3491 8cbcb4fa aurel32
                ctx->nip = dest;
3492 8cbcb4fa aurel32
                GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0);
3493 8cbcb4fa aurel32
                ctx->nip = tmp;
3494 8cbcb4fa aurel32
            }
3495 8cbcb4fa aurel32
            if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3496 8cbcb4fa aurel32
                gen_update_nip(ctx, dest);
3497 64adab3f aurel32
                gen_helper_raise_debug();
3498 8cbcb4fa aurel32
            }
3499 8cbcb4fa aurel32
        }
3500 57fec1fe bellard
        tcg_gen_exit_tb(0);
3501 c1942362 bellard
    }
3502 c53be334 bellard
}
3503 c53be334 bellard
3504 b068d6a7 j_mayer
static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
3505 e1833e1f j_mayer
{
3506 e1833e1f j_mayer
#if defined(TARGET_PPC64)
3507 a2ffb812 aurel32
    if (ctx->sf_mode == 0)
3508 a2ffb812 aurel32
        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
3509 e1833e1f j_mayer
    else
3510 e1833e1f j_mayer
#endif
3511 a2ffb812 aurel32
        tcg_gen_movi_tl(cpu_lr, nip);
3512 e1833e1f j_mayer
}
3513 e1833e1f j_mayer
3514 79aceca5 bellard
/* b ba bl bla */
3515 79aceca5 bellard
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3516 79aceca5 bellard
{
3517 76a66253 j_mayer
    target_ulong li, target;
3518 38a64f9d bellard
3519 8cbcb4fa aurel32
    ctx->exception = POWERPC_EXCP_BRANCH;
3520 38a64f9d bellard
    /* sign extend LI */
3521 76a66253 j_mayer
#if defined(TARGET_PPC64)
3522 d9bce9d9 j_mayer
    if (ctx->sf_mode)
3523 d9bce9d9 j_mayer
        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3524 d9bce9d9 j_mayer
    else
3525 76a66253 j_mayer
#endif
3526 d9bce9d9 j_mayer
        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3527 76a66253 j_mayer
    if (likely(AA(ctx->opcode) == 0))
3528 046d6672 bellard
        target = ctx->nip + li - 4;
3529 79aceca5 bellard
    else
3530 9a64fbe4 bellard
        target = li;
3531 e1833e1f j_mayer
    if (LK(ctx->opcode))
3532 e1833e1f j_mayer
        gen_setlr(ctx, ctx->nip);
3533 c1942362 bellard
    gen_goto_tb(ctx, 0, target);
3534 79aceca5 bellard
}
3535 79aceca5 bellard
3536 e98a6e40 bellard
#define BCOND_IM  0
3537 e98a6e40 bellard
#define BCOND_LR  1
3538 e98a6e40 bellard
#define BCOND_CTR 2
3539 e98a6e40 bellard
3540 b068d6a7 j_mayer
static always_inline void gen_bcond (DisasContext *ctx, int type)
3541 d9bce9d9 j_mayer
{
3542 d9bce9d9 j_mayer
    uint32_t bo = BO(ctx->opcode);
3543 a2ffb812 aurel32
    int l1 = gen_new_label();
3544 a2ffb812 aurel32
    TCGv target;
3545 e98a6e40 bellard
3546 8cbcb4fa aurel32
    ctx->exception = POWERPC_EXCP_BRANCH;
3547 a2ffb812 aurel32
    if (type == BCOND_LR || type == BCOND_CTR) {
3548 a7812ae4 pbrook
        target = tcg_temp_local_new();
3549 a2ffb812 aurel32
        if (type == BCOND_CTR)
3550 a2ffb812 aurel32
            tcg_gen_mov_tl(target, cpu_ctr);
3551 a2ffb812 aurel32
        else
3552 a2ffb812 aurel32
            tcg_gen_mov_tl(target, cpu_lr);
3553 e98a6e40 bellard
    }
3554 e1833e1f j_mayer
    if (LK(ctx->opcode))
3555 e1833e1f j_mayer
        gen_setlr(ctx, ctx->nip);
3556 a2ffb812 aurel32
    l1 = gen_new_label();
3557 a2ffb812 aurel32
    if ((bo & 0x4) == 0) {
3558 a2ffb812 aurel32
        /* Decrement and test CTR */
3559 a7812ae4 pbrook
        TCGv temp = tcg_temp_new();
3560 a2ffb812 aurel32
        if (unlikely(type == BCOND_CTR)) {
3561 a2ffb812 aurel32
            GEN_EXCP_INVAL(ctx);
3562 a2ffb812 aurel32
            return;
3563 a2ffb812 aurel32
        }
3564 a2ffb812 aurel32
        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
3565 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
3566 a2ffb812 aurel32
        if (!ctx->sf_mode)
3567 a2ffb812 aurel32
            tcg_gen_ext32u_tl(temp, cpu_ctr);
3568 a2ffb812 aurel32
        else
3569 d9bce9d9 j_mayer
#endif
3570 a2ffb812 aurel32
            tcg_gen_mov_tl(temp, cpu_ctr);
3571 a2ffb812 aurel32
        if (bo & 0x2) {
3572 a2ffb812 aurel32
            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3573 a2ffb812 aurel32
        } else {
3574 a2ffb812 aurel32
            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
3575 e98a6e40 bellard
        }
3576 a7812ae4 pbrook
        tcg_temp_free(temp);
3577 a2ffb812 aurel32
    }
3578 a2ffb812 aurel32
    if ((bo & 0x10) == 0) {
3579 a2ffb812 aurel32
        /* Test CR */
3580 a2ffb812 aurel32
        uint32_t bi = BI(ctx->opcode);
3581 a2ffb812 aurel32
        uint32_t mask = 1 << (3 - (bi & 0x03));
3582 a7812ae4 pbrook
        TCGv_i32 temp = tcg_temp_new_i32();
3583 a2ffb812 aurel32
3584 d9bce9d9 j_mayer
        if (bo & 0x8) {
3585 a2ffb812 aurel32
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3586 a2ffb812 aurel32
            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
3587 d9bce9d9 j_mayer
        } else {
3588 a2ffb812 aurel32
            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3589 a2ffb812 aurel32
            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
3590 d9bce9d9 j_mayer
        }
3591 a7812ae4 pbrook
        tcg_temp_free_i32(temp);
3592 d9bce9d9 j_mayer
    }
3593 e98a6e40 bellard
    if (type == BCOND_IM) {
3594 a2ffb812 aurel32
        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3595 a2ffb812 aurel32
        if (likely(AA(ctx->opcode) == 0)) {
3596 a2ffb812 aurel32
            gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3597 a2ffb812 aurel32
        } else {
3598 a2ffb812 aurel32
            gen_goto_tb(ctx, 0, li);
3599 a2ffb812 aurel32
        }
3600 c53be334 bellard
        gen_set_label(l1);
3601 c1942362 bellard
        gen_goto_tb(ctx, 1, ctx->nip);
3602 e98a6e40 bellard
    } else {
3603 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
3604 a2ffb812 aurel32
        if (!(ctx->sf_mode))
3605 a2ffb812 aurel32
            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3606 a2ffb812 aurel32
        else
3607 a2ffb812 aurel32
#endif
3608 a2ffb812 aurel32
            tcg_gen_andi_tl(cpu_nip, target, ~3);
3609 a2ffb812 aurel32
        tcg_gen_exit_tb(0);
3610 a2ffb812 aurel32
        gen_set_label(l1);
3611 a2ffb812 aurel32
#if defined(TARGET_PPC64)
3612 a2ffb812 aurel32
        if (!(ctx->sf_mode))
3613 a2ffb812 aurel32
            tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
3614 d9bce9d9 j_mayer
        else
3615 d9bce9d9 j_mayer
#endif
3616 a2ffb812 aurel32
            tcg_gen_movi_tl(cpu_nip, ctx->nip);
3617 57fec1fe bellard
        tcg_gen_exit_tb(0);
3618 08e46e54 j_mayer
    }
3619 e98a6e40 bellard
}
3620 e98a6e40 bellard
3621 e98a6e40 bellard
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3622 3b46e624 ths
{
3623 e98a6e40 bellard
    gen_bcond(ctx, BCOND_IM);
3624 e98a6e40 bellard
}
3625 e98a6e40 bellard
3626 e98a6e40 bellard
GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3627 3b46e624 ths
{
3628 e98a6e40 bellard
    gen_bcond(ctx, BCOND_CTR);
3629 e98a6e40 bellard
}
3630 e98a6e40 bellard
3631 e98a6e40 bellard
GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3632 3b46e624 ths
{
3633 e98a6e40 bellard
    gen_bcond(ctx, BCOND_LR);
3634 e98a6e40 bellard
}
3635 79aceca5 bellard
3636 79aceca5 bellard
/***                      Condition register logical                       ***/
3637 e1571908 aurel32
#define GEN_CRLOGIC(name, tcg_op, opc)                                        \
3638 e1571908 aurel32
GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)                   \
3639 79aceca5 bellard
{                                                                             \
3640 fc0d441e j_mayer
    uint8_t bitmask;                                                          \
3641 fc0d441e j_mayer
    int sh;                                                                   \
3642 a7812ae4 pbrook
    TCGv_i32 t0, t1;                                                          \
3643 fc0d441e j_mayer
    sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03);             \
3644 a7812ae4 pbrook
    t0 = tcg_temp_new_i32();                                                  \
3645 fc0d441e j_mayer
    if (sh > 0)                                                               \
3646 fea0c503 aurel32
        tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh);            \
3647 fc0d441e j_mayer
    else if (sh < 0)                                                          \
3648 fea0c503 aurel32
        tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh);           \
3649 e1571908 aurel32
    else                                                                      \
3650 fea0c503 aurel32
        tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]);                 \
3651 a7812ae4 pbrook
    t1 = tcg_temp_new_i32();                                                  \
3652 fc0d441e j_mayer
    sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03);             \
3653 fc0d441e j_mayer
    if (sh > 0)                                                               \
3654 fea0c503 aurel32
        tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh);            \
3655 fc0d441e j_mayer
    else if (sh < 0)                                                          \
3656 fea0c503 aurel32
        tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh);           \
3657 e1571908 aurel32
    else                                                                      \
3658 fea0c503 aurel32
        tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]);                 \
3659 fea0c503 aurel32
    tcg_op(t0, t0, t1);                                                       \
3660 fc0d441e j_mayer
    bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03));                          \
3661 fea0c503 aurel32
    tcg_gen_andi_i32(t0, t0, bitmask);                                        \
3662 fea0c503 aurel32
    tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask);          \
3663 fea0c503 aurel32
    tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1);                  \
3664 a7812ae4 pbrook
    tcg_temp_free_i32(t0);                                                    \
3665 a7812ae4 pbrook
    tcg_temp_free_i32(t1);                                                    \
3666 79aceca5 bellard
}
3667 79aceca5 bellard
3668 79aceca5 bellard
/* crand */
3669 e1571908 aurel32
GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
3670 79aceca5 bellard
/* crandc */
3671 e1571908 aurel32
GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
3672 79aceca5 bellard
/* creqv */
3673 e1571908 aurel32
GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
3674 79aceca5 bellard
/* crnand */
3675 e1571908 aurel32
GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
3676 79aceca5 bellard
/* crnor */
3677 e1571908 aurel32
GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
3678 79aceca5 bellard
/* cror */
3679 e1571908 aurel32
GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
3680 79aceca5 bellard
/* crorc */
3681 e1571908 aurel32
GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
3682 79aceca5 bellard
/* crxor */
3683 e1571908 aurel32
GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
3684 79aceca5 bellard
/* mcrf */
3685 79aceca5 bellard
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
3686 79aceca5 bellard
{
3687 47e4661c aurel32
    tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
3688 79aceca5 bellard
}
3689 79aceca5 bellard
3690 79aceca5 bellard
/***                           System linkage                              ***/
3691 76db3ba4 aurel32
/* rfi (mem_idx only) */
3692 76a66253 j_mayer
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
3693 79aceca5 bellard
{
3694 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
3695 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
3696 9a64fbe4 bellard
#else
3697 9a64fbe4 bellard
    /* Restore CPU state */
3698 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
3699 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
3700 9fddaa0c bellard
        return;
3701 9a64fbe4 bellard
    }
3702 d72a19f7 aurel32
    gen_helper_rfi();
3703 e1833e1f j_mayer
    GEN_SYNC(ctx);
3704 9a64fbe4 bellard
#endif
3705 79aceca5 bellard
}
3706 79aceca5 bellard
3707 426613db j_mayer
#if defined(TARGET_PPC64)
3708 a750fc0b j_mayer
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
3709 426613db j_mayer
{
3710 426613db j_mayer
#if defined(CONFIG_USER_ONLY)
3711 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
3712 426613db j_mayer
#else
3713 426613db j_mayer
    /* Restore CPU state */
3714 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
3715 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
3716 426613db j_mayer
        return;
3717 426613db j_mayer
    }
3718 d72a19f7 aurel32
    gen_helper_rfid();
3719 e1833e1f j_mayer
    GEN_SYNC(ctx);
3720 426613db j_mayer
#endif
3721 426613db j_mayer
}
3722 426613db j_mayer
3723 5b8105fa j_mayer
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
3724 be147d08 j_mayer
{
3725 be147d08 j_mayer
#if defined(CONFIG_USER_ONLY)
3726 be147d08 j_mayer
    GEN_EXCP_PRIVOPC(ctx);
3727 be147d08 j_mayer
#else
3728 be147d08 j_mayer
    /* Restore CPU state */
3729 76db3ba4 aurel32
    if (unlikely(ctx->mem_idx <= 1)) {
3730 be147d08 j_mayer
        GEN_EXCP_PRIVOPC(ctx);
3731 be147d08 j_mayer
        return;
3732 be147d08 j_mayer
    }
3733 d72a19f7 aurel32
    gen_helper_hrfid();
3734 be147d08 j_mayer
    GEN_SYNC(ctx);
3735 be147d08 j_mayer
#endif
3736 be147d08 j_mayer
}
3737 be147d08 j_mayer
#endif
3738 be147d08 j_mayer
3739 79aceca5 bellard
/* sc */
3740 417bf010 j_mayer
#if defined(CONFIG_USER_ONLY)
3741 417bf010 j_mayer
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3742 417bf010 j_mayer
#else
3743 417bf010 j_mayer
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3744 417bf010 j_mayer
#endif
3745 e1833e1f j_mayer
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
3746 79aceca5 bellard
{
3747 e1833e1f j_mayer
    uint32_t lev;
3748 e1833e1f j_mayer
3749 e1833e1f j_mayer
    lev = (ctx->opcode >> 5) & 0x7F;
3750 417bf010 j_mayer
    GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
3751 79aceca5 bellard
}
3752 79aceca5 bellard
3753 79aceca5 bellard
/***                                Trap                                   ***/
3754 79aceca5 bellard
/* tw */
3755 76a66253 j_mayer
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
3756 79aceca5 bellard
{
3757 cab3bee2 aurel32
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3758 a0ae05aa ths
    /* Update the nip since this might generate a trap exception */
3759 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip);
3760 cab3bee2 aurel32
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3761 cab3bee2 aurel32
    tcg_temp_free_i32(t0);
3762 79aceca5 bellard
}
3763 79aceca5 bellard
3764 79aceca5 bellard
/* twi */
3765 79aceca5 bellard
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3766 79aceca5 bellard
{
3767 cab3bee2 aurel32
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3768 cab3bee2 aurel32
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3769 d9bce9d9 j_mayer
    /* Update the nip since this might generate a trap exception */
3770 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip);
3771 cab3bee2 aurel32
    gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
3772 cab3bee2 aurel32
    tcg_temp_free(t0);
3773 cab3bee2 aurel32
    tcg_temp_free_i32(t1);
3774 79aceca5 bellard
}
3775 79aceca5 bellard
3776 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
3777 d9bce9d9 j_mayer
/* td */
3778 d9bce9d9 j_mayer
GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
3779 d9bce9d9 j_mayer
{
3780 cab3bee2 aurel32
    TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
3781 d9bce9d9 j_mayer
    /* Update the nip since this might generate a trap exception */
3782 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip);
3783 cab3bee2 aurel32
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3784 cab3bee2 aurel32
    tcg_temp_free_i32(t0);
3785 d9bce9d9 j_mayer
}
3786 d9bce9d9 j_mayer
3787 d9bce9d9 j_mayer
/* tdi */
3788 d9bce9d9 j_mayer
GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
3789 d9bce9d9 j_mayer
{
3790 cab3bee2 aurel32
    TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3791 cab3bee2 aurel32
    TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
3792 d9bce9d9 j_mayer
    /* Update the nip since this might generate a trap exception */
3793 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip);
3794 cab3bee2 aurel32
    gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
3795 cab3bee2 aurel32
    tcg_temp_free(t0);
3796 cab3bee2 aurel32
    tcg_temp_free_i32(t1);
3797 d9bce9d9 j_mayer
}
3798 d9bce9d9 j_mayer
#endif
3799 d9bce9d9 j_mayer
3800 79aceca5 bellard
/***                          Processor control                            ***/
3801 79aceca5 bellard
/* mcrxr */
3802 79aceca5 bellard
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
3803 79aceca5 bellard
{
3804 3d7b417e aurel32
    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
3805 3d7b417e aurel32
    tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
3806 269f3e95 aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
3807 79aceca5 bellard
}
3808 79aceca5 bellard
3809 79aceca5 bellard
/* mfcr */
3810 76a66253 j_mayer
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
3811 79aceca5 bellard
{
3812 76a66253 j_mayer
    uint32_t crm, crn;
3813 3b46e624 ths
3814 76a66253 j_mayer
    if (likely(ctx->opcode & 0x00100000)) {
3815 76a66253 j_mayer
        crm = CRM(ctx->opcode);
3816 76a66253 j_mayer
        if (likely((crm ^ (crm - 1)) == 0)) {
3817 76a66253 j_mayer
            crn = ffs(crm);
3818 e1571908 aurel32
            tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
3819 76a66253 j_mayer
        }
3820 d9bce9d9 j_mayer
    } else {
3821 a7812ae4 pbrook
        gen_helper_load_cr(cpu_gpr[rD(ctx->opcode)]);
3822 d9bce9d9 j_mayer
    }
3823 79aceca5 bellard
}
3824 79aceca5 bellard
3825 79aceca5 bellard
/* mfmsr */
3826 79aceca5 bellard
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
3827 79aceca5 bellard
{
3828 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
3829 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
3830 9a64fbe4 bellard
#else
3831 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
3832 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
3833 9fddaa0c bellard
        return;
3834 9a64fbe4 bellard
    }
3835 6527f6ea aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
3836 9a64fbe4 bellard
#endif
3837 79aceca5 bellard
}
3838 79aceca5 bellard
3839 a11b8151 j_mayer
#if 1
3840 6f2d8978 j_mayer
#define SPR_NOACCESS ((void *)(-1UL))
3841 3fc6c082 bellard
#else
3842 3fc6c082 bellard
static void spr_noaccess (void *opaque, int sprn)
3843 3fc6c082 bellard
{
3844 3fc6c082 bellard
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3845 3fc6c082 bellard
    printf("ERROR: try to access SPR %d !\n", sprn);
3846 3fc6c082 bellard
}
3847 3fc6c082 bellard
#define SPR_NOACCESS (&spr_noaccess)
3848 3fc6c082 bellard
#endif
3849 3fc6c082 bellard
3850 79aceca5 bellard
/* mfspr */
3851 b068d6a7 j_mayer
static always_inline void gen_op_mfspr (DisasContext *ctx)
3852 79aceca5 bellard
{
3853 45d827d2 aurel32
    void (*read_cb)(void *opaque, int gprn, int sprn);
3854 79aceca5 bellard
    uint32_t sprn = SPR(ctx->opcode);
3855 79aceca5 bellard
3856 3fc6c082 bellard
#if !defined(CONFIG_USER_ONLY)
3857 76db3ba4 aurel32
    if (ctx->mem_idx == 2)
3858 be147d08 j_mayer
        read_cb = ctx->spr_cb[sprn].hea_read;
3859 76db3ba4 aurel32
    else if (ctx->mem_idx)
3860 3fc6c082 bellard
        read_cb = ctx->spr_cb[sprn].oea_read;
3861 3fc6c082 bellard
    else
3862 9a64fbe4 bellard
#endif
3863 3fc6c082 bellard
        read_cb = ctx->spr_cb[sprn].uea_read;
3864 76a66253 j_mayer
    if (likely(read_cb != NULL)) {
3865 76a66253 j_mayer
        if (likely(read_cb != SPR_NOACCESS)) {
3866 45d827d2 aurel32
            (*read_cb)(ctx, rD(ctx->opcode), sprn);
3867 3fc6c082 bellard
        } else {
3868 3fc6c082 bellard
            /* Privilege exception */
3869 9fceefa7 j_mayer
            /* This is a hack to avoid warnings when running Linux:
3870 9fceefa7 j_mayer
             * this OS breaks the PowerPC virtualisation model,
3871 9fceefa7 j_mayer
             * allowing userland application to read the PVR
3872 9fceefa7 j_mayer
             */
3873 9fceefa7 j_mayer
            if (sprn != SPR_PVR) {
3874 9fceefa7 j_mayer
                if (loglevel != 0) {
3875 6b542af7 j_mayer
                    fprintf(logfile, "Trying to read privileged spr %d %03x at "
3876 077fc206 j_mayer
                            ADDRX "\n", sprn, sprn, ctx->nip);
3877 9fceefa7 j_mayer
                }
3878 077fc206 j_mayer
                printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
3879 077fc206 j_mayer
                       sprn, sprn, ctx->nip);
3880 f24e5695 bellard
            }
3881 e1833e1f j_mayer
            GEN_EXCP_PRIVREG(ctx);
3882 79aceca5 bellard
        }
3883 3fc6c082 bellard
    } else {
3884 3fc6c082 bellard
        /* Not defined */
3885 4a057712 j_mayer
        if (loglevel != 0) {
3886 077fc206 j_mayer
            fprintf(logfile, "Trying to read invalid spr %d %03x at "
3887 077fc206 j_mayer
                    ADDRX "\n", sprn, sprn, ctx->nip);
3888 f24e5695 bellard
        }
3889 077fc206 j_mayer
        printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
3890 077fc206 j_mayer
               sprn, sprn, ctx->nip);
3891 e1833e1f j_mayer
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3892 e1833e1f j_mayer
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
3893 79aceca5 bellard
    }
3894 79aceca5 bellard
}
3895 79aceca5 bellard
3896 3fc6c082 bellard
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
3897 79aceca5 bellard
{
3898 3fc6c082 bellard
    gen_op_mfspr(ctx);
3899 76a66253 j_mayer
}
3900 3fc6c082 bellard
3901 3fc6c082 bellard
/* mftb */
3902 a750fc0b j_mayer
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3903 3fc6c082 bellard
{
3904 3fc6c082 bellard
    gen_op_mfspr(ctx);
3905 79aceca5 bellard
}
3906 79aceca5 bellard
3907 79aceca5 bellard
/* mtcrf */
3908 8dd4983c bellard
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
3909 79aceca5 bellard
{
3910 76a66253 j_mayer
    uint32_t crm, crn;
3911 3b46e624 ths
3912 76a66253 j_mayer
    crm = CRM(ctx->opcode);
3913 76a66253 j_mayer
    if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
3914 a7812ae4 pbrook
        TCGv_i32 temp = tcg_temp_new_i32();
3915 76a66253 j_mayer
        crn = ffs(crm);
3916 a7812ae4 pbrook
        tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3917 a7812ae4 pbrook
        tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
3918 e1571908 aurel32
        tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3919 a7812ae4 pbrook
        tcg_temp_free_i32(temp);
3920 76a66253 j_mayer
    } else {
3921 a7812ae4 pbrook
        TCGv_i32 temp = tcg_const_i32(crm);
3922 a7812ae4 pbrook
        gen_helper_store_cr(cpu_gpr[rS(ctx->opcode)], temp);
3923 a7812ae4 pbrook
        tcg_temp_free_i32(temp);
3924 76a66253 j_mayer
    }
3925 79aceca5 bellard
}
3926 79aceca5 bellard
3927 79aceca5 bellard
/* mtmsr */
3928 426613db j_mayer
#if defined(TARGET_PPC64)
3929 be147d08 j_mayer
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
3930 426613db j_mayer
{
3931 426613db j_mayer
#if defined(CONFIG_USER_ONLY)
3932 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
3933 426613db j_mayer
#else
3934 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
3935 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
3936 426613db j_mayer
        return;
3937 426613db j_mayer
    }
3938 be147d08 j_mayer
    if (ctx->opcode & 0x00010000) {
3939 be147d08 j_mayer
        /* Special form that does not need any synchronisation */
3940 6527f6ea aurel32
        TCGv t0 = tcg_temp_new();
3941 6527f6ea aurel32
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3942 6527f6ea aurel32
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3943 6527f6ea aurel32
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3944 6527f6ea aurel32
        tcg_temp_free(t0);
3945 be147d08 j_mayer
    } else {
3946 056b05f8 j_mayer
        /* XXX: we need to update nip before the store
3947 056b05f8 j_mayer
         *      if we enter power saving mode, we will exit the loop
3948 056b05f8 j_mayer
         *      directly from ppc_store_msr
3949 056b05f8 j_mayer
         */
3950 be147d08 j_mayer
        gen_update_nip(ctx, ctx->nip);
3951 6527f6ea aurel32
        gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3952 be147d08 j_mayer
        /* Must stop the translation as machine state (may have) changed */
3953 be147d08 j_mayer
        /* Note that mtmsr is not always defined as context-synchronizing */
3954 056b05f8 j_mayer
        ctx->exception = POWERPC_EXCP_STOP;
3955 be147d08 j_mayer
    }
3956 426613db j_mayer
#endif
3957 426613db j_mayer
}
3958 426613db j_mayer
#endif
3959 426613db j_mayer
3960 79aceca5 bellard
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
3961 79aceca5 bellard
{
3962 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
3963 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
3964 9a64fbe4 bellard
#else
3965 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
3966 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
3967 9fddaa0c bellard
        return;
3968 9a64fbe4 bellard
    }
3969 be147d08 j_mayer
    if (ctx->opcode & 0x00010000) {
3970 be147d08 j_mayer
        /* Special form that does not need any synchronisation */
3971 6527f6ea aurel32
        TCGv t0 = tcg_temp_new();
3972 6527f6ea aurel32
        tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3973 6527f6ea aurel32
        tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3974 6527f6ea aurel32
        tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3975 6527f6ea aurel32
        tcg_temp_free(t0);
3976 be147d08 j_mayer
    } else {
3977 056b05f8 j_mayer
        /* XXX: we need to update nip before the store
3978 056b05f8 j_mayer
         *      if we enter power saving mode, we will exit the loop
3979 056b05f8 j_mayer
         *      directly from ppc_store_msr
3980 056b05f8 j_mayer
         */
3981 be147d08 j_mayer
        gen_update_nip(ctx, ctx->nip);
3982 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
3983 6527f6ea aurel32
        if (!ctx->sf_mode) {
3984 6527f6ea aurel32
            TCGv t0 = tcg_temp_new();
3985 6527f6ea aurel32
            TCGv t1 = tcg_temp_new();
3986 6527f6ea aurel32
            tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
3987 6527f6ea aurel32
            tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
3988 6527f6ea aurel32
            tcg_gen_or_tl(t0, t0, t1);
3989 6527f6ea aurel32
            tcg_temp_free(t1);
3990 6527f6ea aurel32
            gen_helper_store_msr(t0);
3991 6527f6ea aurel32
            tcg_temp_free(t0);
3992 6527f6ea aurel32
        } else
3993 d9bce9d9 j_mayer
#endif
3994 6527f6ea aurel32
            gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
3995 be147d08 j_mayer
        /* Must stop the translation as machine state (may have) changed */
3996 6527f6ea aurel32
        /* Note that mtmsr is not always defined as context-synchronizing */
3997 056b05f8 j_mayer
        ctx->exception = POWERPC_EXCP_STOP;
3998 be147d08 j_mayer
    }
3999 9a64fbe4 bellard
#endif
4000 79aceca5 bellard
}
4001 79aceca5 bellard
4002 79aceca5 bellard
/* mtspr */
4003 79aceca5 bellard
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
4004 79aceca5 bellard
{
4005 45d827d2 aurel32
    void (*write_cb)(void *opaque, int sprn, int gprn);
4006 79aceca5 bellard
    uint32_t sprn = SPR(ctx->opcode);
4007 79aceca5 bellard
4008 3fc6c082 bellard
#if !defined(CONFIG_USER_ONLY)
4009 76db3ba4 aurel32
    if (ctx->mem_idx == 2)
4010 be147d08 j_mayer
        write_cb = ctx->spr_cb[sprn].hea_write;
4011 76db3ba4 aurel32
    else if (ctx->mem_idx)
4012 3fc6c082 bellard
        write_cb = ctx->spr_cb[sprn].oea_write;
4013 3fc6c082 bellard
    else
4014 9a64fbe4 bellard
#endif
4015 3fc6c082 bellard
        write_cb = ctx->spr_cb[sprn].uea_write;
4016 76a66253 j_mayer
    if (likely(write_cb != NULL)) {
4017 76a66253 j_mayer
        if (likely(write_cb != SPR_NOACCESS)) {
4018 45d827d2 aurel32
            (*write_cb)(ctx, sprn, rS(ctx->opcode));
4019 3fc6c082 bellard
        } else {
4020 3fc6c082 bellard
            /* Privilege exception */
4021 4a057712 j_mayer
            if (loglevel != 0) {
4022 077fc206 j_mayer
                fprintf(logfile, "Trying to write privileged spr %d %03x at "
4023 077fc206 j_mayer
                        ADDRX "\n", sprn, sprn, ctx->nip);
4024 f24e5695 bellard
            }
4025 077fc206 j_mayer
            printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
4026 077fc206 j_mayer
                   sprn, sprn, ctx->nip);
4027 e1833e1f j_mayer
            GEN_EXCP_PRIVREG(ctx);
4028 76a66253 j_mayer
        }
4029 3fc6c082 bellard
    } else {
4030 3fc6c082 bellard
        /* Not defined */
4031 4a057712 j_mayer
        if (loglevel != 0) {
4032 077fc206 j_mayer
            fprintf(logfile, "Trying to write invalid spr %d %03x at "
4033 077fc206 j_mayer
                    ADDRX "\n", sprn, sprn, ctx->nip);
4034 f24e5695 bellard
        }
4035 077fc206 j_mayer
        printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
4036 077fc206 j_mayer
               sprn, sprn, ctx->nip);
4037 e1833e1f j_mayer
        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
4038 e1833e1f j_mayer
                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
4039 79aceca5 bellard
    }
4040 79aceca5 bellard
}
4041 79aceca5 bellard
4042 79aceca5 bellard
/***                         Cache management                              ***/
4043 79aceca5 bellard
/* dcbf */
4044 0db1b20e j_mayer
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
4045 79aceca5 bellard
{
4046 dac454af j_mayer
    /* XXX: specification says this is treated as a load by the MMU */
4047 76db3ba4 aurel32
    TCGv t0;
4048 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_CACHE);
4049 76db3ba4 aurel32
    t0 = tcg_temp_new();
4050 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
4051 76db3ba4 aurel32
    gen_qemu_ld8u(ctx, t0, t0);
4052 fea0c503 aurel32
    tcg_temp_free(t0);
4053 79aceca5 bellard
}
4054 79aceca5 bellard
4055 79aceca5 bellard
/* dcbi (Supervisor only) */
4056 9a64fbe4 bellard
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
4057 79aceca5 bellard
{
4058 a541f297 bellard
#if defined(CONFIG_USER_ONLY)
4059 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
4060 a541f297 bellard
#else
4061 b61f2753 aurel32
    TCGv EA, val;
4062 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4063 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
4064 9fddaa0c bellard
        return;
4065 9a64fbe4 bellard
    }
4066 a7812ae4 pbrook
    EA = tcg_temp_new();
4067 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_CACHE);
4068 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);
4069 a7812ae4 pbrook
    val = tcg_temp_new();
4070 76a66253 j_mayer
    /* XXX: specification says this should be treated as a store by the MMU */
4071 76db3ba4 aurel32
    gen_qemu_ld8u(ctx, val, EA);
4072 76db3ba4 aurel32
    gen_qemu_st8(ctx, val, EA);
4073 b61f2753 aurel32
    tcg_temp_free(val);
4074 b61f2753 aurel32
    tcg_temp_free(EA);
4075 a541f297 bellard
#endif
4076 79aceca5 bellard
}
4077 79aceca5 bellard
4078 79aceca5 bellard
/* dcdst */
4079 9a64fbe4 bellard
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
4080 79aceca5 bellard
{
4081 76a66253 j_mayer
    /* XXX: specification say this is treated as a load by the MMU */
4082 76db3ba4 aurel32
    TCGv t0;
4083 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_CACHE);
4084 76db3ba4 aurel32
    t0 = tcg_temp_new();
4085 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
4086 76db3ba4 aurel32
    gen_qemu_ld8u(ctx, t0, t0);
4087 fea0c503 aurel32
    tcg_temp_free(t0);
4088 79aceca5 bellard
}
4089 79aceca5 bellard
4090 79aceca5 bellard
/* dcbt */
4091 0db1b20e j_mayer
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
4092 79aceca5 bellard
{
4093 0db1b20e j_mayer
    /* interpreted as no-op */
4094 76a66253 j_mayer
    /* XXX: specification say this is treated as a load by the MMU
4095 76a66253 j_mayer
     *      but does not generate any exception
4096 76a66253 j_mayer
     */
4097 79aceca5 bellard
}
4098 79aceca5 bellard
4099 79aceca5 bellard
/* dcbtst */
4100 0db1b20e j_mayer
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
4101 79aceca5 bellard
{
4102 0db1b20e j_mayer
    /* interpreted as no-op */
4103 76a66253 j_mayer
    /* XXX: specification say this is treated as a load by the MMU
4104 76a66253 j_mayer
     *      but does not generate any exception
4105 76a66253 j_mayer
     */
4106 79aceca5 bellard
}
4107 79aceca5 bellard
4108 79aceca5 bellard
/* dcbz */
4109 d63001d1 j_mayer
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
4110 79aceca5 bellard
{
4111 76db3ba4 aurel32
    TCGv t0;
4112 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_CACHE);
4113 799a8c8d aurel32
    /* NIP cannot be restored if the memory exception comes from an helper */
4114 799a8c8d aurel32
    gen_update_nip(ctx, ctx->nip - 4);
4115 76db3ba4 aurel32
    t0 = tcg_temp_new();
4116 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
4117 799a8c8d aurel32
    gen_helper_dcbz(t0);
4118 799a8c8d aurel32
    tcg_temp_free(t0);
4119 d63001d1 j_mayer
}
4120 d63001d1 j_mayer
4121 c7697e1f j_mayer
GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
4122 d63001d1 j_mayer
{
4123 76db3ba4 aurel32
    TCGv t0;
4124 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_CACHE);
4125 799a8c8d aurel32
    /* NIP cannot be restored if the memory exception comes from an helper */
4126 799a8c8d aurel32
    gen_update_nip(ctx, ctx->nip - 4);
4127 76db3ba4 aurel32
    t0 = tcg_temp_new();
4128 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
4129 d63001d1 j_mayer
    if (ctx->opcode & 0x00200000)
4130 799a8c8d aurel32
        gen_helper_dcbz(t0);
4131 d63001d1 j_mayer
    else
4132 799a8c8d aurel32
        gen_helper_dcbz_970(t0);
4133 799a8c8d aurel32
    tcg_temp_free(t0);
4134 79aceca5 bellard
}
4135 79aceca5 bellard
4136 79aceca5 bellard
/* icbi */
4137 1b413d55 j_mayer
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
4138 79aceca5 bellard
{
4139 76db3ba4 aurel32
    TCGv t0;
4140 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_CACHE);
4141 30032c94 j_mayer
    /* NIP cannot be restored if the memory exception comes from an helper */
4142 30032c94 j_mayer
    gen_update_nip(ctx, ctx->nip - 4);
4143 76db3ba4 aurel32
    t0 = tcg_temp_new();
4144 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
4145 37d269df aurel32
    gen_helper_icbi(t0);
4146 37d269df aurel32
    tcg_temp_free(t0);
4147 79aceca5 bellard
}
4148 79aceca5 bellard
4149 79aceca5 bellard
/* Optional: */
4150 79aceca5 bellard
/* dcba */
4151 a750fc0b j_mayer
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
4152 79aceca5 bellard
{
4153 0db1b20e j_mayer
    /* interpreted as no-op */
4154 0db1b20e j_mayer
    /* XXX: specification say this is treated as a store by the MMU
4155 0db1b20e j_mayer
     *      but does not generate any exception
4156 0db1b20e j_mayer
     */
4157 79aceca5 bellard
}
4158 79aceca5 bellard
4159 79aceca5 bellard
/***                    Segment register manipulation                      ***/
4160 79aceca5 bellard
/* Supervisor only: */
4161 79aceca5 bellard
/* mfsr */
4162 79aceca5 bellard
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
4163 79aceca5 bellard
{
4164 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
4165 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
4166 9a64fbe4 bellard
#else
4167 74d37793 aurel32
    TCGv t0;
4168 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4169 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
4170 9fddaa0c bellard
        return;
4171 9a64fbe4 bellard
    }
4172 74d37793 aurel32
    t0 = tcg_const_tl(SR(ctx->opcode));
4173 74d37793 aurel32
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4174 74d37793 aurel32
    tcg_temp_free(t0);
4175 9a64fbe4 bellard
#endif
4176 79aceca5 bellard
}
4177 79aceca5 bellard
4178 79aceca5 bellard
/* mfsrin */
4179 9a64fbe4 bellard
GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
4180 79aceca5 bellard
{
4181 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
4182 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
4183 9a64fbe4 bellard
#else
4184 74d37793 aurel32
    TCGv t0;
4185 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4186 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
4187 9fddaa0c bellard
        return;
4188 9a64fbe4 bellard
    }
4189 74d37793 aurel32
    t0 = tcg_temp_new();
4190 74d37793 aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4191 74d37793 aurel32
    tcg_gen_andi_tl(t0, t0, 0xF);
4192 74d37793 aurel32
    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4193 74d37793 aurel32
    tcg_temp_free(t0);
4194 9a64fbe4 bellard
#endif
4195 79aceca5 bellard
}
4196 79aceca5 bellard
4197 79aceca5 bellard
/* mtsr */
4198 e63c59cb bellard
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
4199 79aceca5 bellard
{
4200 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
4201 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
4202 9a64fbe4 bellard
#else
4203 74d37793 aurel32
    TCGv t0;
4204 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4205 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
4206 9fddaa0c bellard
        return;
4207 9a64fbe4 bellard
    }
4208 74d37793 aurel32
    t0 = tcg_const_tl(SR(ctx->opcode));
4209 74d37793 aurel32
    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4210 74d37793 aurel32
    tcg_temp_free(t0);
4211 9a64fbe4 bellard
#endif
4212 79aceca5 bellard
}
4213 79aceca5 bellard
4214 79aceca5 bellard
/* mtsrin */
4215 9a64fbe4 bellard
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
4216 79aceca5 bellard
{
4217 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
4218 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
4219 9a64fbe4 bellard
#else
4220 74d37793 aurel32
    TCGv t0;
4221 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4222 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
4223 9fddaa0c bellard
        return;
4224 9a64fbe4 bellard
    }
4225 74d37793 aurel32
    t0 = tcg_temp_new();
4226 74d37793 aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4227 74d37793 aurel32
    tcg_gen_andi_tl(t0, t0, 0xF);
4228 74d37793 aurel32
    gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
4229 74d37793 aurel32
    tcg_temp_free(t0);
4230 9a64fbe4 bellard
#endif
4231 79aceca5 bellard
}
4232 79aceca5 bellard
4233 12de9a39 j_mayer
#if defined(TARGET_PPC64)
4234 12de9a39 j_mayer
/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
4235 12de9a39 j_mayer
/* mfsr */
4236 c7697e1f j_mayer
GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
4237 12de9a39 j_mayer
{
4238 12de9a39 j_mayer
#if defined(CONFIG_USER_ONLY)
4239 12de9a39 j_mayer
    GEN_EXCP_PRIVREG(ctx);
4240 12de9a39 j_mayer
#else
4241 74d37793 aurel32
    TCGv t0;
4242 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4243 12de9a39 j_mayer
        GEN_EXCP_PRIVREG(ctx);
4244 12de9a39 j_mayer
        return;
4245 12de9a39 j_mayer
    }
4246 74d37793 aurel32
    t0 = tcg_const_tl(SR(ctx->opcode));
4247 74d37793 aurel32
    gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0);
4248 74d37793 aurel32
    tcg_temp_free(t0);
4249 12de9a39 j_mayer
#endif
4250 12de9a39 j_mayer
}
4251 12de9a39 j_mayer
4252 12de9a39 j_mayer
/* mfsrin */
4253 c7697e1f j_mayer
GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
4254 c7697e1f j_mayer
             PPC_SEGMENT_64B)
4255 12de9a39 j_mayer
{
4256 12de9a39 j_mayer
#if defined(CONFIG_USER_ONLY)
4257 12de9a39 j_mayer
    GEN_EXCP_PRIVREG(ctx);
4258 12de9a39 j_mayer
#else
4259 74d37793 aurel32
    TCGv t0;
4260 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4261 12de9a39 j_mayer
        GEN_EXCP_PRIVREG(ctx);
4262 12de9a39 j_mayer
        return;
4263 12de9a39 j_mayer
    }
4264 74d37793 aurel32
    t0 = tcg_temp_new();
4265 74d37793 aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4266 74d37793 aurel32
    tcg_gen_andi_tl(t0, t0, 0xF);
4267 74d37793 aurel32
    gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0);
4268 74d37793 aurel32
    tcg_temp_free(t0);
4269 12de9a39 j_mayer
#endif
4270 12de9a39 j_mayer
}
4271 12de9a39 j_mayer
4272 12de9a39 j_mayer
/* mtsr */
4273 c7697e1f j_mayer
GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
4274 12de9a39 j_mayer
{
4275 12de9a39 j_mayer
#if defined(CONFIG_USER_ONLY)
4276 12de9a39 j_mayer
    GEN_EXCP_PRIVREG(ctx);
4277 12de9a39 j_mayer
#else
4278 74d37793 aurel32
    TCGv t0;
4279 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4280 12de9a39 j_mayer
        GEN_EXCP_PRIVREG(ctx);
4281 12de9a39 j_mayer
        return;
4282 12de9a39 j_mayer
    }
4283 74d37793 aurel32
    t0 = tcg_const_tl(SR(ctx->opcode));
4284 74d37793 aurel32
    gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]);
4285 74d37793 aurel32
    tcg_temp_free(t0);
4286 12de9a39 j_mayer
#endif
4287 12de9a39 j_mayer
}
4288 12de9a39 j_mayer
4289 12de9a39 j_mayer
/* mtsrin */
4290 c7697e1f j_mayer
GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
4291 c7697e1f j_mayer
             PPC_SEGMENT_64B)
4292 12de9a39 j_mayer
{
4293 12de9a39 j_mayer
#if defined(CONFIG_USER_ONLY)
4294 12de9a39 j_mayer
    GEN_EXCP_PRIVREG(ctx);
4295 12de9a39 j_mayer
#else
4296 74d37793 aurel32
    TCGv t0;
4297 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4298 12de9a39 j_mayer
        GEN_EXCP_PRIVREG(ctx);
4299 12de9a39 j_mayer
        return;
4300 12de9a39 j_mayer
    }
4301 74d37793 aurel32
    t0 = tcg_temp_new();
4302 74d37793 aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4303 74d37793 aurel32
    tcg_gen_andi_tl(t0, t0, 0xF);
4304 74d37793 aurel32
    gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]);
4305 74d37793 aurel32
    tcg_temp_free(t0);
4306 12de9a39 j_mayer
#endif
4307 12de9a39 j_mayer
}
4308 12de9a39 j_mayer
#endif /* defined(TARGET_PPC64) */
4309 12de9a39 j_mayer
4310 79aceca5 bellard
/***                      Lookaside buffer management                      ***/
4311 76db3ba4 aurel32
/* Optional & mem_idx only: */
4312 79aceca5 bellard
/* tlbia */
4313 3fc6c082 bellard
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
4314 79aceca5 bellard
{
4315 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
4316 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
4317 9a64fbe4 bellard
#else
4318 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4319 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
4320 9fddaa0c bellard
        return;
4321 9a64fbe4 bellard
    }
4322 74d37793 aurel32
    gen_helper_tlbia();
4323 9a64fbe4 bellard
#endif
4324 79aceca5 bellard
}
4325 79aceca5 bellard
4326 79aceca5 bellard
/* tlbie */
4327 76a66253 j_mayer
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
4328 79aceca5 bellard
{
4329 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
4330 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
4331 9a64fbe4 bellard
#else
4332 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4333 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
4334 9fddaa0c bellard
        return;
4335 9a64fbe4 bellard
    }
4336 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
4337 74d37793 aurel32
    if (!ctx->sf_mode) {
4338 74d37793 aurel32
        TCGv t0 = tcg_temp_new();
4339 74d37793 aurel32
        tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4340 74d37793 aurel32
        gen_helper_tlbie(t0);
4341 74d37793 aurel32
        tcg_temp_free(t0);
4342 74d37793 aurel32
    } else
4343 d9bce9d9 j_mayer
#endif
4344 74d37793 aurel32
        gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4345 9a64fbe4 bellard
#endif
4346 79aceca5 bellard
}
4347 79aceca5 bellard
4348 79aceca5 bellard
/* tlbsync */
4349 76a66253 j_mayer
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
4350 79aceca5 bellard
{
4351 9a64fbe4 bellard
#if defined(CONFIG_USER_ONLY)
4352 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
4353 9a64fbe4 bellard
#else
4354 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4355 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
4356 9fddaa0c bellard
        return;
4357 9a64fbe4 bellard
    }
4358 9a64fbe4 bellard
    /* This has no effect: it should ensure that all previous
4359 9a64fbe4 bellard
     * tlbie have completed
4360 9a64fbe4 bellard
     */
4361 e1833e1f j_mayer
    GEN_STOP(ctx);
4362 9a64fbe4 bellard
#endif
4363 79aceca5 bellard
}
4364 79aceca5 bellard
4365 426613db j_mayer
#if defined(TARGET_PPC64)
4366 426613db j_mayer
/* slbia */
4367 426613db j_mayer
GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
4368 426613db j_mayer
{
4369 426613db j_mayer
#if defined(CONFIG_USER_ONLY)
4370 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
4371 426613db j_mayer
#else
4372 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4373 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
4374 426613db j_mayer
        return;
4375 426613db j_mayer
    }
4376 74d37793 aurel32
    gen_helper_slbia();
4377 426613db j_mayer
#endif
4378 426613db j_mayer
}
4379 426613db j_mayer
4380 426613db j_mayer
/* slbie */
4381 426613db j_mayer
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
4382 426613db j_mayer
{
4383 426613db j_mayer
#if defined(CONFIG_USER_ONLY)
4384 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
4385 426613db j_mayer
#else
4386 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
4387 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
4388 426613db j_mayer
        return;
4389 426613db j_mayer
    }
4390 74d37793 aurel32
    gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
4391 426613db j_mayer
#endif
4392 426613db j_mayer
}
4393 426613db j_mayer
#endif
4394 426613db j_mayer
4395 79aceca5 bellard
/***                              External control                         ***/
4396 79aceca5 bellard
/* Optional: */
4397 111bfab3 bellard
/* eciwx */
4398 79aceca5 bellard
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
4399 79aceca5 bellard
{
4400 76db3ba4 aurel32
    TCGv t0;
4401 fa407c03 aurel32
    /* Should check EAR[E] ! */
4402 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_EXT);
4403 76db3ba4 aurel32
    t0 = tcg_temp_new();
4404 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
4405 fa407c03 aurel32
    gen_check_align(ctx, t0, 0x03);
4406 76db3ba4 aurel32
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4407 fa407c03 aurel32
    tcg_temp_free(t0);
4408 76a66253 j_mayer
}
4409 76a66253 j_mayer
4410 76a66253 j_mayer
/* ecowx */
4411 76a66253 j_mayer
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
4412 76a66253 j_mayer
{
4413 76db3ba4 aurel32
    TCGv t0;
4414 fa407c03 aurel32
    /* Should check EAR[E] ! */
4415 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_EXT);
4416 76db3ba4 aurel32
    t0 = tcg_temp_new();
4417 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
4418 fa407c03 aurel32
    gen_check_align(ctx, t0, 0x03);
4419 76db3ba4 aurel32
    gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
4420 fa407c03 aurel32
    tcg_temp_free(t0);
4421 76a66253 j_mayer
}
4422 76a66253 j_mayer
4423 76a66253 j_mayer
/* PowerPC 601 specific instructions */
4424 76a66253 j_mayer
/* abs - abs. */
4425 76a66253 j_mayer
GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
4426 76a66253 j_mayer
{
4427 22e0e173 aurel32
    int l1 = gen_new_label();
4428 22e0e173 aurel32
    int l2 = gen_new_label();
4429 22e0e173 aurel32
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4430 22e0e173 aurel32
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4431 22e0e173 aurel32
    tcg_gen_br(l2);
4432 22e0e173 aurel32
    gen_set_label(l1);
4433 22e0e173 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4434 22e0e173 aurel32
    gen_set_label(l2);
4435 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4436 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4437 76a66253 j_mayer
}
4438 76a66253 j_mayer
4439 76a66253 j_mayer
/* abso - abso. */
4440 76a66253 j_mayer
GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
4441 76a66253 j_mayer
{
4442 22e0e173 aurel32
    int l1 = gen_new_label();
4443 22e0e173 aurel32
    int l2 = gen_new_label();
4444 22e0e173 aurel32
    int l3 = gen_new_label();
4445 22e0e173 aurel32
    /* Start with XER OV disabled, the most likely case */
4446 22e0e173 aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4447 22e0e173 aurel32
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4448 22e0e173 aurel32
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4449 22e0e173 aurel32
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4450 22e0e173 aurel32
    tcg_gen_br(l2);
4451 22e0e173 aurel32
    gen_set_label(l1);
4452 22e0e173 aurel32
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4453 22e0e173 aurel32
    tcg_gen_br(l3);
4454 22e0e173 aurel32
    gen_set_label(l2);
4455 22e0e173 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4456 22e0e173 aurel32
    gen_set_label(l3);
4457 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4458 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4459 76a66253 j_mayer
}
4460 76a66253 j_mayer
4461 76a66253 j_mayer
/* clcs */
4462 a750fc0b j_mayer
GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
4463 76a66253 j_mayer
{
4464 22e0e173 aurel32
    TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4465 22e0e173 aurel32
    gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
4466 22e0e173 aurel32
    tcg_temp_free_i32(t0);
4467 c7697e1f j_mayer
    /* Rc=1 sets CR0 to an undefined state */
4468 76a66253 j_mayer
}
4469 76a66253 j_mayer
4470 76a66253 j_mayer
/* div - div. */
4471 76a66253 j_mayer
GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
4472 76a66253 j_mayer
{
4473 22e0e173 aurel32
    gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4474 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4475 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4476 76a66253 j_mayer
}
4477 76a66253 j_mayer
4478 76a66253 j_mayer
/* divo - divo. */
4479 76a66253 j_mayer
GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
4480 76a66253 j_mayer
{
4481 22e0e173 aurel32
    gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4482 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4483 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4484 76a66253 j_mayer
}
4485 76a66253 j_mayer
4486 76a66253 j_mayer
/* divs - divs. */
4487 76a66253 j_mayer
GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
4488 76a66253 j_mayer
{
4489 22e0e173 aurel32
    gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4490 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4491 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4492 76a66253 j_mayer
}
4493 76a66253 j_mayer
4494 76a66253 j_mayer
/* divso - divso. */
4495 76a66253 j_mayer
GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
4496 76a66253 j_mayer
{
4497 22e0e173 aurel32
    gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4498 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4499 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4500 76a66253 j_mayer
}
4501 76a66253 j_mayer
4502 76a66253 j_mayer
/* doz - doz. */
4503 76a66253 j_mayer
GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
4504 76a66253 j_mayer
{
4505 22e0e173 aurel32
    int l1 = gen_new_label();
4506 22e0e173 aurel32
    int l2 = gen_new_label();
4507 22e0e173 aurel32
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4508 22e0e173 aurel32
    tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4509 22e0e173 aurel32
    tcg_gen_br(l2);
4510 22e0e173 aurel32
    gen_set_label(l1);
4511 22e0e173 aurel32
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4512 22e0e173 aurel32
    gen_set_label(l2);
4513 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4514 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4515 76a66253 j_mayer
}
4516 76a66253 j_mayer
4517 76a66253 j_mayer
/* dozo - dozo. */
4518 76a66253 j_mayer
GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
4519 76a66253 j_mayer
{
4520 22e0e173 aurel32
    int l1 = gen_new_label();
4521 22e0e173 aurel32
    int l2 = gen_new_label();
4522 22e0e173 aurel32
    TCGv t0 = tcg_temp_new();
4523 22e0e173 aurel32
    TCGv t1 = tcg_temp_new();
4524 22e0e173 aurel32
    TCGv t2 = tcg_temp_new();
4525 22e0e173 aurel32
    /* Start with XER OV disabled, the most likely case */
4526 22e0e173 aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4527 22e0e173 aurel32
    tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4528 22e0e173 aurel32
    tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4529 22e0e173 aurel32
    tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4530 22e0e173 aurel32
    tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4531 22e0e173 aurel32
    tcg_gen_andc_tl(t1, t1, t2);
4532 22e0e173 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4533 22e0e173 aurel32
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4534 22e0e173 aurel32
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4535 22e0e173 aurel32
    tcg_gen_br(l2);
4536 22e0e173 aurel32
    gen_set_label(l1);
4537 22e0e173 aurel32
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4538 22e0e173 aurel32
    gen_set_label(l2);
4539 22e0e173 aurel32
    tcg_temp_free(t0);
4540 22e0e173 aurel32
    tcg_temp_free(t1);
4541 22e0e173 aurel32
    tcg_temp_free(t2);
4542 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4543 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4544 76a66253 j_mayer
}
4545 76a66253 j_mayer
4546 76a66253 j_mayer
/* dozi */
4547 76a66253 j_mayer
GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4548 76a66253 j_mayer
{
4549 22e0e173 aurel32
    target_long simm = SIMM(ctx->opcode);
4550 22e0e173 aurel32
    int l1 = gen_new_label();
4551 22e0e173 aurel32
    int l2 = gen_new_label();
4552 22e0e173 aurel32
    tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4553 22e0e173 aurel32
    tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4554 22e0e173 aurel32
    tcg_gen_br(l2);
4555 22e0e173 aurel32
    gen_set_label(l1);
4556 22e0e173 aurel32
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4557 22e0e173 aurel32
    gen_set_label(l2);
4558 22e0e173 aurel32
    if (unlikely(Rc(ctx->opcode) != 0))
4559 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4560 76a66253 j_mayer
}
4561 76a66253 j_mayer
4562 76a66253 j_mayer
/* lscbx - lscbx. */
4563 76a66253 j_mayer
GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
4564 76a66253 j_mayer
{
4565 bdb4b689 aurel32
    TCGv t0 = tcg_temp_new();
4566 bdb4b689 aurel32
    TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4567 bdb4b689 aurel32
    TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4568 bdb4b689 aurel32
    TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
4569 76a66253 j_mayer
4570 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
4571 76a66253 j_mayer
    /* NIP cannot be restored if the memory exception comes from an helper */
4572 d9bce9d9 j_mayer
    gen_update_nip(ctx, ctx->nip - 4);
4573 bdb4b689 aurel32
    gen_helper_lscbx(t0, t0, t1, t2, t3);
4574 bdb4b689 aurel32
    tcg_temp_free_i32(t1);
4575 bdb4b689 aurel32
    tcg_temp_free_i32(t2);
4576 bdb4b689 aurel32
    tcg_temp_free_i32(t3);
4577 3d7b417e aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4578 bdb4b689 aurel32
    tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
4579 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4580 bdb4b689 aurel32
        gen_set_Rc0(ctx, t0);
4581 bdb4b689 aurel32
    tcg_temp_free(t0);
4582 76a66253 j_mayer
}
4583 76a66253 j_mayer
4584 76a66253 j_mayer
/* maskg - maskg. */
4585 76a66253 j_mayer
GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
4586 76a66253 j_mayer
{
4587 22e0e173 aurel32
    int l1 = gen_new_label();
4588 22e0e173 aurel32
    TCGv t0 = tcg_temp_new();
4589 22e0e173 aurel32
    TCGv t1 = tcg_temp_new();
4590 22e0e173 aurel32
    TCGv t2 = tcg_temp_new();
4591 22e0e173 aurel32
    TCGv t3 = tcg_temp_new();
4592 22e0e173 aurel32
    tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4593 22e0e173 aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4594 22e0e173 aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4595 22e0e173 aurel32
    tcg_gen_addi_tl(t2, t0, 1);
4596 22e0e173 aurel32
    tcg_gen_shr_tl(t2, t3, t2);
4597 22e0e173 aurel32
    tcg_gen_shr_tl(t3, t3, t1);
4598 22e0e173 aurel32
    tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4599 22e0e173 aurel32
    tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4600 22e0e173 aurel32
    tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4601 22e0e173 aurel32
    gen_set_label(l1);
4602 22e0e173 aurel32
    tcg_temp_free(t0);
4603 22e0e173 aurel32
    tcg_temp_free(t1);
4604 22e0e173 aurel32
    tcg_temp_free(t2);
4605 22e0e173 aurel32
    tcg_temp_free(t3);
4606 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4607 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4608 76a66253 j_mayer
}
4609 76a66253 j_mayer
4610 76a66253 j_mayer
/* maskir - maskir. */
4611 76a66253 j_mayer
GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
4612 76a66253 j_mayer
{
4613 22e0e173 aurel32
    TCGv t0 = tcg_temp_new();
4614 22e0e173 aurel32
    TCGv t1 = tcg_temp_new();
4615 22e0e173 aurel32
    tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4616 22e0e173 aurel32
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4617 22e0e173 aurel32
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4618 22e0e173 aurel32
    tcg_temp_free(t0);
4619 22e0e173 aurel32
    tcg_temp_free(t1);
4620 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4621 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4622 76a66253 j_mayer
}
4623 76a66253 j_mayer
4624 76a66253 j_mayer
/* mul - mul. */
4625 76a66253 j_mayer
GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
4626 76a66253 j_mayer
{
4627 22e0e173 aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();
4628 22e0e173 aurel32
    TCGv_i64 t1 = tcg_temp_new_i64();
4629 22e0e173 aurel32
    TCGv t2 = tcg_temp_new();
4630 22e0e173 aurel32
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4631 22e0e173 aurel32
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4632 22e0e173 aurel32
    tcg_gen_mul_i64(t0, t0, t1);
4633 22e0e173 aurel32
    tcg_gen_trunc_i64_tl(t2, t0);
4634 22e0e173 aurel32
    gen_store_spr(SPR_MQ, t2);
4635 22e0e173 aurel32
    tcg_gen_shri_i64(t1, t0, 32);
4636 22e0e173 aurel32
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4637 22e0e173 aurel32
    tcg_temp_free_i64(t0);
4638 22e0e173 aurel32
    tcg_temp_free_i64(t1);
4639 22e0e173 aurel32
    tcg_temp_free(t2);
4640 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4641 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4642 76a66253 j_mayer
}
4643 76a66253 j_mayer
4644 76a66253 j_mayer
/* mulo - mulo. */
4645 76a66253 j_mayer
GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
4646 76a66253 j_mayer
{
4647 22e0e173 aurel32
    int l1 = gen_new_label();
4648 22e0e173 aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();
4649 22e0e173 aurel32
    TCGv_i64 t1 = tcg_temp_new_i64();
4650 22e0e173 aurel32
    TCGv t2 = tcg_temp_new();
4651 22e0e173 aurel32
    /* Start with XER OV disabled, the most likely case */
4652 22e0e173 aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4653 22e0e173 aurel32
    tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4654 22e0e173 aurel32
    tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4655 22e0e173 aurel32
    tcg_gen_mul_i64(t0, t0, t1);
4656 22e0e173 aurel32
    tcg_gen_trunc_i64_tl(t2, t0);
4657 22e0e173 aurel32
    gen_store_spr(SPR_MQ, t2);
4658 22e0e173 aurel32
    tcg_gen_shri_i64(t1, t0, 32);
4659 22e0e173 aurel32
    tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4660 22e0e173 aurel32
    tcg_gen_ext32s_i64(t1, t0);
4661 22e0e173 aurel32
    tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4662 22e0e173 aurel32
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4663 22e0e173 aurel32
    gen_set_label(l1);
4664 22e0e173 aurel32
    tcg_temp_free_i64(t0);
4665 22e0e173 aurel32
    tcg_temp_free_i64(t1);
4666 22e0e173 aurel32
    tcg_temp_free(t2);
4667 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4668 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4669 76a66253 j_mayer
}
4670 76a66253 j_mayer
4671 76a66253 j_mayer
/* nabs - nabs. */
4672 76a66253 j_mayer
GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
4673 76a66253 j_mayer
{
4674 22e0e173 aurel32
    int l1 = gen_new_label();
4675 22e0e173 aurel32
    int l2 = gen_new_label();
4676 22e0e173 aurel32
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4677 22e0e173 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4678 22e0e173 aurel32
    tcg_gen_br(l2);
4679 22e0e173 aurel32
    gen_set_label(l1);
4680 22e0e173 aurel32
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4681 22e0e173 aurel32
    gen_set_label(l2);
4682 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4683 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4684 76a66253 j_mayer
}
4685 76a66253 j_mayer
4686 76a66253 j_mayer
/* nabso - nabso. */
4687 76a66253 j_mayer
GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
4688 76a66253 j_mayer
{
4689 22e0e173 aurel32
    int l1 = gen_new_label();
4690 22e0e173 aurel32
    int l2 = gen_new_label();
4691 22e0e173 aurel32
    tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4692 22e0e173 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4693 22e0e173 aurel32
    tcg_gen_br(l2);
4694 22e0e173 aurel32
    gen_set_label(l1);
4695 22e0e173 aurel32
    tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4696 22e0e173 aurel32
    gen_set_label(l2);
4697 22e0e173 aurel32
    /* nabs never overflows */
4698 22e0e173 aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4699 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4700 22e0e173 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
4701 76a66253 j_mayer
}
4702 76a66253 j_mayer
4703 76a66253 j_mayer
/* rlmi - rlmi. */
4704 76a66253 j_mayer
GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4705 76a66253 j_mayer
{
4706 7487953d aurel32
    uint32_t mb = MB(ctx->opcode);
4707 7487953d aurel32
    uint32_t me = ME(ctx->opcode);
4708 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4709 7487953d aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4710 7487953d aurel32
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4711 7487953d aurel32
    tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4712 7487953d aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4713 7487953d aurel32
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4714 7487953d aurel32
    tcg_temp_free(t0);
4715 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4716 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4717 76a66253 j_mayer
}
4718 76a66253 j_mayer
4719 76a66253 j_mayer
/* rrib - rrib. */
4720 76a66253 j_mayer
GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
4721 76a66253 j_mayer
{
4722 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4723 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4724 7487953d aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4725 7487953d aurel32
    tcg_gen_movi_tl(t1, 0x80000000);
4726 7487953d aurel32
    tcg_gen_shr_tl(t1, t1, t0);
4727 7487953d aurel32
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4728 7487953d aurel32
    tcg_gen_and_tl(t0, t0, t1);
4729 7487953d aurel32
    tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4730 7487953d aurel32
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4731 7487953d aurel32
    tcg_temp_free(t0);
4732 7487953d aurel32
    tcg_temp_free(t1);
4733 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4734 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4735 76a66253 j_mayer
}
4736 76a66253 j_mayer
4737 76a66253 j_mayer
/* sle - sle. */
4738 76a66253 j_mayer
GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
4739 76a66253 j_mayer
{
4740 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4741 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4742 7487953d aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4743 7487953d aurel32
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4744 7487953d aurel32
    tcg_gen_subfi_tl(t1, 32, t1);
4745 7487953d aurel32
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4746 7487953d aurel32
    tcg_gen_or_tl(t1, t0, t1);
4747 7487953d aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4748 7487953d aurel32
    gen_store_spr(SPR_MQ, t1);
4749 7487953d aurel32
    tcg_temp_free(t0);
4750 7487953d aurel32
    tcg_temp_free(t1);
4751 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4752 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4753 76a66253 j_mayer
}
4754 76a66253 j_mayer
4755 76a66253 j_mayer
/* sleq - sleq. */
4756 76a66253 j_mayer
GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
4757 76a66253 j_mayer
{
4758 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4759 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4760 7487953d aurel32
    TCGv t2 = tcg_temp_new();
4761 7487953d aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4762 7487953d aurel32
    tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4763 7487953d aurel32
    tcg_gen_shl_tl(t2, t2, t0);
4764 7487953d aurel32
    tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4765 7487953d aurel32
    gen_load_spr(t1, SPR_MQ);
4766 7487953d aurel32
    gen_store_spr(SPR_MQ, t0);
4767 7487953d aurel32
    tcg_gen_and_tl(t0, t0, t2);
4768 7487953d aurel32
    tcg_gen_andc_tl(t1, t1, t2);
4769 7487953d aurel32
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4770 7487953d aurel32
    tcg_temp_free(t0);
4771 7487953d aurel32
    tcg_temp_free(t1);
4772 7487953d aurel32
    tcg_temp_free(t2);
4773 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4774 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4775 76a66253 j_mayer
}
4776 76a66253 j_mayer
4777 76a66253 j_mayer
/* sliq - sliq. */
4778 76a66253 j_mayer
GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
4779 76a66253 j_mayer
{
4780 7487953d aurel32
    int sh = SH(ctx->opcode);
4781 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4782 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4783 7487953d aurel32
    tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4784 7487953d aurel32
    tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4785 7487953d aurel32
    tcg_gen_or_tl(t1, t0, t1);
4786 7487953d aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4787 7487953d aurel32
    gen_store_spr(SPR_MQ, t1);
4788 7487953d aurel32
    tcg_temp_free(t0);
4789 7487953d aurel32
    tcg_temp_free(t1);
4790 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4791 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4792 76a66253 j_mayer
}
4793 76a66253 j_mayer
4794 76a66253 j_mayer
/* slliq - slliq. */
4795 76a66253 j_mayer
GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
4796 76a66253 j_mayer
{
4797 7487953d aurel32
    int sh = SH(ctx->opcode);
4798 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4799 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4800 7487953d aurel32
    tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4801 7487953d aurel32
    gen_load_spr(t1, SPR_MQ);
4802 7487953d aurel32
    gen_store_spr(SPR_MQ, t0);
4803 7487953d aurel32
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU << sh));
4804 7487953d aurel32
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
4805 7487953d aurel32
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4806 7487953d aurel32
    tcg_temp_free(t0);
4807 7487953d aurel32
    tcg_temp_free(t1);
4808 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4809 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4810 76a66253 j_mayer
}
4811 76a66253 j_mayer
4812 76a66253 j_mayer
/* sllq - sllq. */
4813 76a66253 j_mayer
GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
4814 76a66253 j_mayer
{
4815 7487953d aurel32
    int l1 = gen_new_label();
4816 7487953d aurel32
    int l2 = gen_new_label();
4817 7487953d aurel32
    TCGv t0 = tcg_temp_local_new();
4818 7487953d aurel32
    TCGv t1 = tcg_temp_local_new();
4819 7487953d aurel32
    TCGv t2 = tcg_temp_local_new();
4820 7487953d aurel32
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4821 7487953d aurel32
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4822 7487953d aurel32
    tcg_gen_shl_tl(t1, t1, t2);
4823 7487953d aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4824 7487953d aurel32
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4825 7487953d aurel32
    gen_load_spr(t0, SPR_MQ);
4826 7487953d aurel32
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4827 7487953d aurel32
    tcg_gen_br(l2);
4828 7487953d aurel32
    gen_set_label(l1);
4829 7487953d aurel32
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4830 7487953d aurel32
    gen_load_spr(t2, SPR_MQ);
4831 7487953d aurel32
    tcg_gen_andc_tl(t1, t2, t1);
4832 7487953d aurel32
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4833 7487953d aurel32
    gen_set_label(l2);
4834 7487953d aurel32
    tcg_temp_free(t0);
4835 7487953d aurel32
    tcg_temp_free(t1);
4836 7487953d aurel32
    tcg_temp_free(t2);
4837 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4838 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4839 76a66253 j_mayer
}
4840 76a66253 j_mayer
4841 76a66253 j_mayer
/* slq - slq. */
4842 76a66253 j_mayer
GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
4843 76a66253 j_mayer
{
4844 7487953d aurel32
    int l1 = gen_new_label();
4845 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4846 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4847 7487953d aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4848 7487953d aurel32
    tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4849 7487953d aurel32
    tcg_gen_subfi_tl(t1, 32, t1);
4850 7487953d aurel32
    tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4851 7487953d aurel32
    tcg_gen_or_tl(t1, t0, t1);
4852 7487953d aurel32
    gen_store_spr(SPR_MQ, t1);
4853 7487953d aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4854 7487953d aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4855 7487953d aurel32
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4856 7487953d aurel32
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4857 7487953d aurel32
    gen_set_label(l1);
4858 7487953d aurel32
    tcg_temp_free(t0);
4859 7487953d aurel32
    tcg_temp_free(t1);
4860 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4861 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4862 76a66253 j_mayer
}
4863 76a66253 j_mayer
4864 d9bce9d9 j_mayer
/* sraiq - sraiq. */
4865 76a66253 j_mayer
GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
4866 76a66253 j_mayer
{
4867 7487953d aurel32
    int sh = SH(ctx->opcode);
4868 7487953d aurel32
    int l1 = gen_new_label();
4869 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4870 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4871 7487953d aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4872 7487953d aurel32
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4873 7487953d aurel32
    tcg_gen_or_tl(t0, t0, t1);
4874 7487953d aurel32
    gen_store_spr(SPR_MQ, t0);
4875 7487953d aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4876 7487953d aurel32
    tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4877 7487953d aurel32
    tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4878 7487953d aurel32
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4879 7487953d aurel32
    gen_set_label(l1);
4880 7487953d aurel32
    tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
4881 7487953d aurel32
    tcg_temp_free(t0);
4882 7487953d aurel32
    tcg_temp_free(t1);
4883 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4884 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4885 76a66253 j_mayer
}
4886 76a66253 j_mayer
4887 76a66253 j_mayer
/* sraq - sraq. */
4888 76a66253 j_mayer
GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
4889 76a66253 j_mayer
{
4890 7487953d aurel32
    int l1 = gen_new_label();
4891 7487953d aurel32
    int l2 = gen_new_label();
4892 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4893 7487953d aurel32
    TCGv t1 = tcg_temp_local_new();
4894 7487953d aurel32
    TCGv t2 = tcg_temp_local_new();
4895 7487953d aurel32
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4896 7487953d aurel32
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4897 7487953d aurel32
    tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
4898 7487953d aurel32
    tcg_gen_subfi_tl(t2, 32, t2);
4899 7487953d aurel32
    tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
4900 7487953d aurel32
    tcg_gen_or_tl(t0, t0, t2);
4901 7487953d aurel32
    gen_store_spr(SPR_MQ, t0);
4902 7487953d aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4903 7487953d aurel32
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
4904 7487953d aurel32
    tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
4905 7487953d aurel32
    tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
4906 7487953d aurel32
    gen_set_label(l1);
4907 7487953d aurel32
    tcg_temp_free(t0);
4908 7487953d aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4909 7487953d aurel32
    tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4910 7487953d aurel32
    tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4911 7487953d aurel32
    tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4912 7487953d aurel32
    tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4913 7487953d aurel32
    gen_set_label(l2);
4914 7487953d aurel32
    tcg_temp_free(t1);
4915 7487953d aurel32
    tcg_temp_free(t2);
4916 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4917 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4918 76a66253 j_mayer
}
4919 76a66253 j_mayer
4920 76a66253 j_mayer
/* sre - sre. */
4921 76a66253 j_mayer
GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
4922 76a66253 j_mayer
{
4923 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4924 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4925 7487953d aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4926 7487953d aurel32
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4927 7487953d aurel32
    tcg_gen_subfi_tl(t1, 32, t1);
4928 7487953d aurel32
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4929 7487953d aurel32
    tcg_gen_or_tl(t1, t0, t1);
4930 7487953d aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4931 7487953d aurel32
    gen_store_spr(SPR_MQ, t1);
4932 7487953d aurel32
    tcg_temp_free(t0);
4933 7487953d aurel32
    tcg_temp_free(t1);
4934 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4935 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4936 76a66253 j_mayer
}
4937 76a66253 j_mayer
4938 76a66253 j_mayer
/* srea - srea. */
4939 76a66253 j_mayer
GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
4940 76a66253 j_mayer
{
4941 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4942 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4943 7487953d aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4944 7487953d aurel32
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4945 7487953d aurel32
    gen_store_spr(SPR_MQ, t0);
4946 7487953d aurel32
    tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
4947 7487953d aurel32
    tcg_temp_free(t0);
4948 7487953d aurel32
    tcg_temp_free(t1);
4949 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4950 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4951 76a66253 j_mayer
}
4952 76a66253 j_mayer
4953 76a66253 j_mayer
/* sreq */
4954 76a66253 j_mayer
GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
4955 76a66253 j_mayer
{
4956 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4957 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4958 7487953d aurel32
    TCGv t2 = tcg_temp_new();
4959 7487953d aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4960 7487953d aurel32
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4961 7487953d aurel32
    tcg_gen_shr_tl(t1, t1, t0);
4962 7487953d aurel32
    tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4963 7487953d aurel32
    gen_load_spr(t2, SPR_MQ);
4964 7487953d aurel32
    gen_store_spr(SPR_MQ, t0);
4965 7487953d aurel32
    tcg_gen_and_tl(t0, t0, t1);
4966 7487953d aurel32
    tcg_gen_andc_tl(t2, t2, t1);
4967 7487953d aurel32
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4968 7487953d aurel32
    tcg_temp_free(t0);
4969 7487953d aurel32
    tcg_temp_free(t1);
4970 7487953d aurel32
    tcg_temp_free(t2);
4971 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4972 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4973 76a66253 j_mayer
}
4974 76a66253 j_mayer
4975 76a66253 j_mayer
/* sriq */
4976 76a66253 j_mayer
GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
4977 76a66253 j_mayer
{
4978 7487953d aurel32
    int sh = SH(ctx->opcode);
4979 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4980 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4981 7487953d aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4982 7487953d aurel32
    tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4983 7487953d aurel32
    tcg_gen_or_tl(t1, t0, t1);
4984 7487953d aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4985 7487953d aurel32
    gen_store_spr(SPR_MQ, t1);
4986 7487953d aurel32
    tcg_temp_free(t0);
4987 7487953d aurel32
    tcg_temp_free(t1);
4988 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
4989 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
4990 76a66253 j_mayer
}
4991 76a66253 j_mayer
4992 76a66253 j_mayer
/* srliq */
4993 76a66253 j_mayer
GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
4994 76a66253 j_mayer
{
4995 7487953d aurel32
    int sh = SH(ctx->opcode);
4996 7487953d aurel32
    TCGv t0 = tcg_temp_new();
4997 7487953d aurel32
    TCGv t1 = tcg_temp_new();
4998 7487953d aurel32
    tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4999 7487953d aurel32
    gen_load_spr(t1, SPR_MQ);
5000 7487953d aurel32
    gen_store_spr(SPR_MQ, t0);
5001 7487953d aurel32
    tcg_gen_andi_tl(t0, t0,  (0xFFFFFFFFU >> sh));
5002 7487953d aurel32
    tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
5003 7487953d aurel32
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5004 7487953d aurel32
    tcg_temp_free(t0);
5005 7487953d aurel32
    tcg_temp_free(t1);
5006 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
5007 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5008 76a66253 j_mayer
}
5009 76a66253 j_mayer
5010 76a66253 j_mayer
/* srlq */
5011 76a66253 j_mayer
GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
5012 76a66253 j_mayer
{
5013 7487953d aurel32
    int l1 = gen_new_label();
5014 7487953d aurel32
    int l2 = gen_new_label();
5015 7487953d aurel32
    TCGv t0 = tcg_temp_local_new();
5016 7487953d aurel32
    TCGv t1 = tcg_temp_local_new();
5017 7487953d aurel32
    TCGv t2 = tcg_temp_local_new();
5018 7487953d aurel32
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5019 7487953d aurel32
    tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5020 7487953d aurel32
    tcg_gen_shr_tl(t2, t1, t2);
5021 7487953d aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5022 7487953d aurel32
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5023 7487953d aurel32
    gen_load_spr(t0, SPR_MQ);
5024 7487953d aurel32
    tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5025 7487953d aurel32
    tcg_gen_br(l2);
5026 7487953d aurel32
    gen_set_label(l1);
5027 7487953d aurel32
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5028 7487953d aurel32
    tcg_gen_and_tl(t0, t0, t2);
5029 7487953d aurel32
    gen_load_spr(t1, SPR_MQ);
5030 7487953d aurel32
    tcg_gen_andc_tl(t1, t1, t2);
5031 7487953d aurel32
    tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5032 7487953d aurel32
    gen_set_label(l2);
5033 7487953d aurel32
    tcg_temp_free(t0);
5034 7487953d aurel32
    tcg_temp_free(t1);
5035 7487953d aurel32
    tcg_temp_free(t2);
5036 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
5037 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5038 76a66253 j_mayer
}
5039 76a66253 j_mayer
5040 76a66253 j_mayer
/* srq */
5041 76a66253 j_mayer
GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
5042 76a66253 j_mayer
{
5043 7487953d aurel32
    int l1 = gen_new_label();
5044 7487953d aurel32
    TCGv t0 = tcg_temp_new();
5045 7487953d aurel32
    TCGv t1 = tcg_temp_new();
5046 7487953d aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5047 7487953d aurel32
    tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5048 7487953d aurel32
    tcg_gen_subfi_tl(t1, 32, t1);
5049 7487953d aurel32
    tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5050 7487953d aurel32
    tcg_gen_or_tl(t1, t0, t1);
5051 7487953d aurel32
    gen_store_spr(SPR_MQ, t1);
5052 7487953d aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5053 7487953d aurel32
    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5054 7487953d aurel32
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5055 7487953d aurel32
    tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5056 7487953d aurel32
    gen_set_label(l1);
5057 7487953d aurel32
    tcg_temp_free(t0);
5058 7487953d aurel32
    tcg_temp_free(t1);
5059 76a66253 j_mayer
    if (unlikely(Rc(ctx->opcode) != 0))
5060 7487953d aurel32
        gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
5061 76a66253 j_mayer
}
5062 76a66253 j_mayer
5063 76a66253 j_mayer
/* PowerPC 602 specific instructions */
5064 76a66253 j_mayer
/* dsa  */
5065 76a66253 j_mayer
GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
5066 76a66253 j_mayer
{
5067 76a66253 j_mayer
    /* XXX: TODO */
5068 e1833e1f j_mayer
    GEN_EXCP_INVAL(ctx);
5069 76a66253 j_mayer
}
5070 76a66253 j_mayer
5071 76a66253 j_mayer
/* esa */
5072 76a66253 j_mayer
GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
5073 76a66253 j_mayer
{
5074 76a66253 j_mayer
    /* XXX: TODO */
5075 e1833e1f j_mayer
    GEN_EXCP_INVAL(ctx);
5076 76a66253 j_mayer
}
5077 76a66253 j_mayer
5078 76a66253 j_mayer
/* mfrom */
5079 76a66253 j_mayer
GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
5080 76a66253 j_mayer
{
5081 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5082 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5083 76a66253 j_mayer
#else
5084 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5085 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5086 76a66253 j_mayer
        return;
5087 76a66253 j_mayer
    }
5088 cf02a65c aurel32
    gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5089 76a66253 j_mayer
#endif
5090 76a66253 j_mayer
}
5091 76a66253 j_mayer
5092 76a66253 j_mayer
/* 602 - 603 - G2 TLB management */
5093 76a66253 j_mayer
/* tlbld */
5094 c7697e1f j_mayer
GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
5095 76a66253 j_mayer
{
5096 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5097 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5098 76a66253 j_mayer
#else
5099 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5100 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5101 76a66253 j_mayer
        return;
5102 76a66253 j_mayer
    }
5103 74d37793 aurel32
    gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5104 76a66253 j_mayer
#endif
5105 76a66253 j_mayer
}
5106 76a66253 j_mayer
5107 76a66253 j_mayer
/* tlbli */
5108 c7697e1f j_mayer
GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
5109 76a66253 j_mayer
{
5110 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5111 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5112 76a66253 j_mayer
#else
5113 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5114 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5115 76a66253 j_mayer
        return;
5116 76a66253 j_mayer
    }
5117 74d37793 aurel32
    gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5118 76a66253 j_mayer
#endif
5119 76a66253 j_mayer
}
5120 76a66253 j_mayer
5121 7dbe11ac j_mayer
/* 74xx TLB management */
5122 7dbe11ac j_mayer
/* tlbld */
5123 c7697e1f j_mayer
GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
5124 7dbe11ac j_mayer
{
5125 7dbe11ac j_mayer
#if defined(CONFIG_USER_ONLY)
5126 7dbe11ac j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5127 7dbe11ac j_mayer
#else
5128 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5129 7dbe11ac j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5130 7dbe11ac j_mayer
        return;
5131 7dbe11ac j_mayer
    }
5132 74d37793 aurel32
    gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
5133 7dbe11ac j_mayer
#endif
5134 7dbe11ac j_mayer
}
5135 7dbe11ac j_mayer
5136 7dbe11ac j_mayer
/* tlbli */
5137 c7697e1f j_mayer
GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
5138 7dbe11ac j_mayer
{
5139 7dbe11ac j_mayer
#if defined(CONFIG_USER_ONLY)
5140 7dbe11ac j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5141 7dbe11ac j_mayer
#else
5142 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5143 7dbe11ac j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5144 7dbe11ac j_mayer
        return;
5145 7dbe11ac j_mayer
    }
5146 74d37793 aurel32
    gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
5147 7dbe11ac j_mayer
#endif
5148 7dbe11ac j_mayer
}
5149 7dbe11ac j_mayer
5150 76a66253 j_mayer
/* POWER instructions not in PowerPC 601 */
5151 76a66253 j_mayer
/* clf */
5152 76a66253 j_mayer
GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
5153 76a66253 j_mayer
{
5154 76a66253 j_mayer
    /* Cache line flush: implemented as no-op */
5155 76a66253 j_mayer
}
5156 76a66253 j_mayer
5157 76a66253 j_mayer
/* cli */
5158 76a66253 j_mayer
GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
5159 76a66253 j_mayer
{
5160 7f75ffd3 blueswir1
    /* Cache line invalidate: privileged and treated as no-op */
5161 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5162 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5163 76a66253 j_mayer
#else
5164 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5165 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5166 76a66253 j_mayer
        return;
5167 76a66253 j_mayer
    }
5168 76a66253 j_mayer
#endif
5169 76a66253 j_mayer
}
5170 76a66253 j_mayer
5171 76a66253 j_mayer
/* dclst */
5172 76a66253 j_mayer
GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
5173 76a66253 j_mayer
{
5174 76a66253 j_mayer
    /* Data cache line store: treated as no-op */
5175 76a66253 j_mayer
}
5176 76a66253 j_mayer
5177 76a66253 j_mayer
GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
5178 76a66253 j_mayer
{
5179 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5180 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5181 76a66253 j_mayer
#else
5182 74d37793 aurel32
    int ra = rA(ctx->opcode);
5183 74d37793 aurel32
    int rd = rD(ctx->opcode);
5184 74d37793 aurel32
    TCGv t0;
5185 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5186 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5187 76a66253 j_mayer
        return;
5188 76a66253 j_mayer
    }
5189 74d37793 aurel32
    t0 = tcg_temp_new();
5190 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
5191 74d37793 aurel32
    tcg_gen_shri_tl(t0, t0, 28);
5192 74d37793 aurel32
    tcg_gen_andi_tl(t0, t0, 0xF);
5193 74d37793 aurel32
    gen_helper_load_sr(cpu_gpr[rd], t0);
5194 74d37793 aurel32
    tcg_temp_free(t0);
5195 76a66253 j_mayer
    if (ra != 0 && ra != rd)
5196 74d37793 aurel32
        tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
5197 76a66253 j_mayer
#endif
5198 76a66253 j_mayer
}
5199 76a66253 j_mayer
5200 76a66253 j_mayer
GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
5201 76a66253 j_mayer
{
5202 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5203 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5204 76a66253 j_mayer
#else
5205 22e0e173 aurel32
    TCGv t0;
5206 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5207 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5208 76a66253 j_mayer
        return;
5209 76a66253 j_mayer
    }
5210 22e0e173 aurel32
    t0 = tcg_temp_new();
5211 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
5212 22e0e173 aurel32
    gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
5213 22e0e173 aurel32
    tcg_temp_free(t0);
5214 76a66253 j_mayer
#endif
5215 76a66253 j_mayer
}
5216 76a66253 j_mayer
5217 76a66253 j_mayer
GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
5218 76a66253 j_mayer
{
5219 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5220 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5221 76a66253 j_mayer
#else
5222 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5223 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5224 76a66253 j_mayer
        return;
5225 76a66253 j_mayer
    }
5226 d72a19f7 aurel32
    gen_helper_rfsvc();
5227 e1833e1f j_mayer
    GEN_SYNC(ctx);
5228 76a66253 j_mayer
#endif
5229 76a66253 j_mayer
}
5230 76a66253 j_mayer
5231 76a66253 j_mayer
/* svc is not implemented for now */
5232 76a66253 j_mayer
5233 76a66253 j_mayer
/* POWER2 specific instructions */
5234 76a66253 j_mayer
/* Quad manipulation (load/store two floats at a time) */
5235 76a66253 j_mayer
5236 76a66253 j_mayer
/* lfq */
5237 76a66253 j_mayer
GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5238 76a66253 j_mayer
{
5239 01a4afeb aurel32
    int rd = rD(ctx->opcode);
5240 76db3ba4 aurel32
    TCGv t0;
5241 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);
5242 76db3ba4 aurel32
    t0 = tcg_temp_new();
5243 76db3ba4 aurel32
    gen_addr_imm_index(ctx, t0, 0);
5244 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5245 76db3ba4 aurel32
    gen_addr_add(ctx, t0, t0, 8);
5246 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5247 01a4afeb aurel32
    tcg_temp_free(t0);
5248 76a66253 j_mayer
}
5249 76a66253 j_mayer
5250 76a66253 j_mayer
/* lfqu */
5251 76a66253 j_mayer
GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5252 76a66253 j_mayer
{
5253 76a66253 j_mayer
    int ra = rA(ctx->opcode);
5254 01a4afeb aurel32
    int rd = rD(ctx->opcode);
5255 76db3ba4 aurel32
    TCGv t0, t1;
5256 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);
5257 76db3ba4 aurel32
    t0 = tcg_temp_new();
5258 76db3ba4 aurel32
    t1 = tcg_temp_new();
5259 76db3ba4 aurel32
    gen_addr_imm_index(ctx, t0, 0);
5260 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5261 76db3ba4 aurel32
    gen_addr_add(ctx, t1, t0, 8);
5262 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5263 76a66253 j_mayer
    if (ra != 0)
5264 01a4afeb aurel32
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5265 01a4afeb aurel32
    tcg_temp_free(t0);
5266 01a4afeb aurel32
    tcg_temp_free(t1);
5267 76a66253 j_mayer
}
5268 76a66253 j_mayer
5269 76a66253 j_mayer
/* lfqux */
5270 76a66253 j_mayer
GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
5271 76a66253 j_mayer
{
5272 76a66253 j_mayer
    int ra = rA(ctx->opcode);
5273 01a4afeb aurel32
    int rd = rD(ctx->opcode);
5274 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);
5275 76db3ba4 aurel32
    TCGv t0, t1;
5276 76db3ba4 aurel32
    t0 = tcg_temp_new();
5277 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
5278 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5279 76db3ba4 aurel32
    t1 = tcg_temp_new();
5280 76db3ba4 aurel32
    gen_addr_add(ctx, t1, t0, 8);
5281 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5282 76db3ba4 aurel32
    tcg_temp_free(t1);
5283 76a66253 j_mayer
    if (ra != 0)
5284 01a4afeb aurel32
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5285 01a4afeb aurel32
    tcg_temp_free(t0);
5286 76a66253 j_mayer
}
5287 76a66253 j_mayer
5288 76a66253 j_mayer
/* lfqx */
5289 76a66253 j_mayer
GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
5290 76a66253 j_mayer
{
5291 01a4afeb aurel32
    int rd = rD(ctx->opcode);
5292 76db3ba4 aurel32
    TCGv t0;
5293 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);
5294 76db3ba4 aurel32
    t0 = tcg_temp_new();
5295 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
5296 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5297 76db3ba4 aurel32
    gen_addr_add(ctx, t0, t0, 8);
5298 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5299 01a4afeb aurel32
    tcg_temp_free(t0);
5300 76a66253 j_mayer
}
5301 76a66253 j_mayer
5302 76a66253 j_mayer
/* stfq */
5303 76a66253 j_mayer
GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5304 76a66253 j_mayer
{
5305 01a4afeb aurel32
    int rd = rD(ctx->opcode);
5306 76db3ba4 aurel32
    TCGv t0;
5307 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);
5308 76db3ba4 aurel32
    t0 = tcg_temp_new();
5309 76db3ba4 aurel32
    gen_addr_imm_index(ctx, t0, 0);
5310 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5311 76db3ba4 aurel32
    gen_addr_add(ctx, t0, t0, 8);
5312 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5313 01a4afeb aurel32
    tcg_temp_free(t0);
5314 76a66253 j_mayer
}
5315 76a66253 j_mayer
5316 76a66253 j_mayer
/* stfqu */
5317 76a66253 j_mayer
GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5318 76a66253 j_mayer
{
5319 76a66253 j_mayer
    int ra = rA(ctx->opcode);
5320 01a4afeb aurel32
    int rd = rD(ctx->opcode);
5321 76db3ba4 aurel32
    TCGv t0, t1;
5322 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);
5323 76db3ba4 aurel32
    t0 = tcg_temp_new();
5324 76db3ba4 aurel32
    gen_addr_imm_index(ctx, t0, 0);
5325 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5326 76db3ba4 aurel32
    t1 = tcg_temp_new();
5327 76db3ba4 aurel32
    gen_addr_add(ctx, t1, t0, 8);
5328 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5329 76db3ba4 aurel32
    tcg_temp_free(t1);
5330 76a66253 j_mayer
    if (ra != 0)
5331 01a4afeb aurel32
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5332 01a4afeb aurel32
    tcg_temp_free(t0);
5333 76a66253 j_mayer
}
5334 76a66253 j_mayer
5335 76a66253 j_mayer
/* stfqux */
5336 76a66253 j_mayer
GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
5337 76a66253 j_mayer
{
5338 76a66253 j_mayer
    int ra = rA(ctx->opcode);
5339 01a4afeb aurel32
    int rd = rD(ctx->opcode);
5340 76db3ba4 aurel32
    TCGv t0, t1;
5341 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);
5342 76db3ba4 aurel32
    t0 = tcg_temp_new();
5343 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
5344 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5345 76db3ba4 aurel32
    t1 = tcg_temp_new();
5346 76db3ba4 aurel32
    gen_addr_add(ctx, t1, t0, 8);
5347 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5348 76db3ba4 aurel32
    tcg_temp_free(t1);
5349 76a66253 j_mayer
    if (ra != 0)
5350 01a4afeb aurel32
        tcg_gen_mov_tl(cpu_gpr[ra], t0);
5351 01a4afeb aurel32
    tcg_temp_free(t0);
5352 76a66253 j_mayer
}
5353 76a66253 j_mayer
5354 76a66253 j_mayer
/* stfqx */
5355 76a66253 j_mayer
GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
5356 76a66253 j_mayer
{
5357 01a4afeb aurel32
    int rd = rD(ctx->opcode);
5358 76db3ba4 aurel32
    TCGv t0;
5359 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_FLOAT);
5360 76db3ba4 aurel32
    t0 = tcg_temp_new();
5361 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
5362 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5363 76db3ba4 aurel32
    gen_addr_add(ctx, t0, t0, 8);
5364 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
5365 01a4afeb aurel32
    tcg_temp_free(t0);
5366 76a66253 j_mayer
}
5367 76a66253 j_mayer
5368 76a66253 j_mayer
/* BookE specific instructions */
5369 2662a059 j_mayer
/* XXX: not implemented on 440 ? */
5370 05332d70 j_mayer
GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
5371 76a66253 j_mayer
{
5372 76a66253 j_mayer
    /* XXX: TODO */
5373 e1833e1f j_mayer
    GEN_EXCP_INVAL(ctx);
5374 76a66253 j_mayer
}
5375 76a66253 j_mayer
5376 2662a059 j_mayer
/* XXX: not implemented on 440 ? */
5377 05332d70 j_mayer
GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
5378 76a66253 j_mayer
{
5379 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5380 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5381 76a66253 j_mayer
#else
5382 74d37793 aurel32
    TCGv t0;
5383 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5384 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5385 76a66253 j_mayer
        return;
5386 76a66253 j_mayer
    }
5387 ec72e276 aurel32
    t0 = tcg_temp_new();
5388 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
5389 74d37793 aurel32
    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
5390 74d37793 aurel32
    tcg_temp_free(t0);
5391 76a66253 j_mayer
#endif
5392 76a66253 j_mayer
}
5393 76a66253 j_mayer
5394 76a66253 j_mayer
/* All 405 MAC instructions are translated here */
5395 b068d6a7 j_mayer
static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5396 b068d6a7 j_mayer
                                                int opc2, int opc3,
5397 b068d6a7 j_mayer
                                                int ra, int rb, int rt, int Rc)
5398 76a66253 j_mayer
{
5399 182608d4 aurel32
    TCGv t0, t1;
5400 182608d4 aurel32
5401 a7812ae4 pbrook
    t0 = tcg_temp_local_new();
5402 a7812ae4 pbrook
    t1 = tcg_temp_local_new();
5403 182608d4 aurel32
5404 76a66253 j_mayer
    switch (opc3 & 0x0D) {
5405 76a66253 j_mayer
    case 0x05:
5406 76a66253 j_mayer
        /* macchw    - macchw.    - macchwo   - macchwo.   */
5407 76a66253 j_mayer
        /* macchws   - macchws.   - macchwso  - macchwso.  */
5408 76a66253 j_mayer
        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
5409 76a66253 j_mayer
        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
5410 76a66253 j_mayer
        /* mulchw - mulchw. */
5411 182608d4 aurel32
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5412 182608d4 aurel32
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5413 182608d4 aurel32
        tcg_gen_ext16s_tl(t1, t1);
5414 76a66253 j_mayer
        break;
5415 76a66253 j_mayer
    case 0x04:
5416 76a66253 j_mayer
        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
5417 76a66253 j_mayer
        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
5418 76a66253 j_mayer
        /* mulchwu - mulchwu. */
5419 182608d4 aurel32
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5420 182608d4 aurel32
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5421 182608d4 aurel32
        tcg_gen_ext16u_tl(t1, t1);
5422 76a66253 j_mayer
        break;
5423 76a66253 j_mayer
    case 0x01:
5424 76a66253 j_mayer
        /* machhw    - machhw.    - machhwo   - machhwo.   */
5425 76a66253 j_mayer
        /* machhws   - machhws.   - machhwso  - machhwso.  */
5426 76a66253 j_mayer
        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
5427 76a66253 j_mayer
        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
5428 76a66253 j_mayer
        /* mulhhw - mulhhw. */
5429 182608d4 aurel32
        tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5430 182608d4 aurel32
        tcg_gen_ext16s_tl(t0, t0);
5431 182608d4 aurel32
        tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5432 182608d4 aurel32
        tcg_gen_ext16s_tl(t1, t1);
5433 76a66253 j_mayer
        break;
5434 76a66253 j_mayer
    case 0x00:
5435 76a66253 j_mayer
        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
5436 76a66253 j_mayer
        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
5437 76a66253 j_mayer
        /* mulhhwu - mulhhwu. */
5438 182608d4 aurel32
        tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5439 182608d4 aurel32
        tcg_gen_ext16u_tl(t0, t0);
5440 182608d4 aurel32
        tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5441 182608d4 aurel32
        tcg_gen_ext16u_tl(t1, t1);
5442 76a66253 j_mayer
        break;
5443 76a66253 j_mayer
    case 0x0D:
5444 76a66253 j_mayer
        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
5445 76a66253 j_mayer
        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
5446 76a66253 j_mayer
        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
5447 76a66253 j_mayer
        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
5448 76a66253 j_mayer
        /* mullhw - mullhw. */
5449 182608d4 aurel32
        tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5450 182608d4 aurel32
        tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5451 76a66253 j_mayer
        break;
5452 76a66253 j_mayer
    case 0x0C:
5453 76a66253 j_mayer
        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
5454 76a66253 j_mayer
        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
5455 76a66253 j_mayer
        /* mullhwu - mullhwu. */
5456 182608d4 aurel32
        tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5457 182608d4 aurel32
        tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5458 76a66253 j_mayer
        break;
5459 76a66253 j_mayer
    }
5460 76a66253 j_mayer
    if (opc2 & 0x04) {
5461 182608d4 aurel32
        /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5462 182608d4 aurel32
        tcg_gen_mul_tl(t1, t0, t1);
5463 182608d4 aurel32
        if (opc2 & 0x02) {
5464 182608d4 aurel32
            /* nmultiply-and-accumulate (0x0E) */
5465 182608d4 aurel32
            tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5466 182608d4 aurel32
        } else {
5467 182608d4 aurel32
            /* multiply-and-accumulate (0x0C) */
5468 182608d4 aurel32
            tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5469 182608d4 aurel32
        }
5470 182608d4 aurel32
5471 182608d4 aurel32
        if (opc3 & 0x12) {
5472 182608d4 aurel32
            /* Check overflow and/or saturate */
5473 182608d4 aurel32
            int l1 = gen_new_label();
5474 182608d4 aurel32
5475 182608d4 aurel32
            if (opc3 & 0x10) {
5476 182608d4 aurel32
                /* Start with XER OV disabled, the most likely case */
5477 182608d4 aurel32
                tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5478 182608d4 aurel32
            }
5479 182608d4 aurel32
            if (opc3 & 0x01) {
5480 182608d4 aurel32
                /* Signed */
5481 182608d4 aurel32
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5482 182608d4 aurel32
                tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5483 182608d4 aurel32
                tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5484 182608d4 aurel32
                tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
5485 bdc4e053 aurel32
                if (opc3 & 0x02) {
5486 182608d4 aurel32
                    /* Saturate */
5487 182608d4 aurel32
                    tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5488 182608d4 aurel32
                    tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5489 182608d4 aurel32
                }
5490 182608d4 aurel32
            } else {
5491 182608d4 aurel32
                /* Unsigned */
5492 182608d4 aurel32
                tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5493 bdc4e053 aurel32
                if (opc3 & 0x02) {
5494 182608d4 aurel32
                    /* Saturate */
5495 182608d4 aurel32
                    tcg_gen_movi_tl(t0, UINT32_MAX);
5496 182608d4 aurel32
                }
5497 182608d4 aurel32
            }
5498 182608d4 aurel32
            if (opc3 & 0x10) {
5499 182608d4 aurel32
                /* Check overflow */
5500 182608d4 aurel32
                tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5501 182608d4 aurel32
            }
5502 182608d4 aurel32
            gen_set_label(l1);
5503 182608d4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
5504 182608d4 aurel32
        }
5505 182608d4 aurel32
    } else {
5506 182608d4 aurel32
        tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5507 76a66253 j_mayer
    }
5508 182608d4 aurel32
    tcg_temp_free(t0);
5509 182608d4 aurel32
    tcg_temp_free(t1);
5510 76a66253 j_mayer
    if (unlikely(Rc) != 0) {
5511 76a66253 j_mayer
        /* Update Rc0 */
5512 182608d4 aurel32
        gen_set_Rc0(ctx, cpu_gpr[rt]);
5513 76a66253 j_mayer
    }
5514 76a66253 j_mayer
}
5515 76a66253 j_mayer
5516 a750fc0b j_mayer
#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
5517 a750fc0b j_mayer
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)                  \
5518 76a66253 j_mayer
{                                                                             \
5519 76a66253 j_mayer
    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
5520 76a66253 j_mayer
                         rD(ctx->opcode), Rc(ctx->opcode));                   \
5521 76a66253 j_mayer
}
5522 76a66253 j_mayer
5523 76a66253 j_mayer
/* macchw    - macchw.    */
5524 a750fc0b j_mayer
GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5525 76a66253 j_mayer
/* macchwo   - macchwo.   */
5526 a750fc0b j_mayer
GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5527 76a66253 j_mayer
/* macchws   - macchws.   */
5528 a750fc0b j_mayer
GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5529 76a66253 j_mayer
/* macchwso  - macchwso.  */
5530 a750fc0b j_mayer
GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5531 76a66253 j_mayer
/* macchwsu  - macchwsu.  */
5532 a750fc0b j_mayer
GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5533 76a66253 j_mayer
/* macchwsuo - macchwsuo. */
5534 a750fc0b j_mayer
GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5535 76a66253 j_mayer
/* macchwu   - macchwu.   */
5536 a750fc0b j_mayer
GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5537 76a66253 j_mayer
/* macchwuo  - macchwuo.  */
5538 a750fc0b j_mayer
GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5539 76a66253 j_mayer
/* machhw    - machhw.    */
5540 a750fc0b j_mayer
GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5541 76a66253 j_mayer
/* machhwo   - machhwo.   */
5542 a750fc0b j_mayer
GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5543 76a66253 j_mayer
/* machhws   - machhws.   */
5544 a750fc0b j_mayer
GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5545 76a66253 j_mayer
/* machhwso  - machhwso.  */
5546 a750fc0b j_mayer
GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5547 76a66253 j_mayer
/* machhwsu  - machhwsu.  */
5548 a750fc0b j_mayer
GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5549 76a66253 j_mayer
/* machhwsuo - machhwsuo. */
5550 a750fc0b j_mayer
GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5551 76a66253 j_mayer
/* machhwu   - machhwu.   */
5552 a750fc0b j_mayer
GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5553 76a66253 j_mayer
/* machhwuo  - machhwuo.  */
5554 a750fc0b j_mayer
GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5555 76a66253 j_mayer
/* maclhw    - maclhw.    */
5556 a750fc0b j_mayer
GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5557 76a66253 j_mayer
/* maclhwo   - maclhwo.   */
5558 a750fc0b j_mayer
GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5559 76a66253 j_mayer
/* maclhws   - maclhws.   */
5560 a750fc0b j_mayer
GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5561 76a66253 j_mayer
/* maclhwso  - maclhwso.  */
5562 a750fc0b j_mayer
GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5563 76a66253 j_mayer
/* maclhwu   - maclhwu.   */
5564 a750fc0b j_mayer
GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5565 76a66253 j_mayer
/* maclhwuo  - maclhwuo.  */
5566 a750fc0b j_mayer
GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5567 76a66253 j_mayer
/* maclhwsu  - maclhwsu.  */
5568 a750fc0b j_mayer
GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5569 76a66253 j_mayer
/* maclhwsuo - maclhwsuo. */
5570 a750fc0b j_mayer
GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5571 76a66253 j_mayer
/* nmacchw   - nmacchw.   */
5572 a750fc0b j_mayer
GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5573 76a66253 j_mayer
/* nmacchwo  - nmacchwo.  */
5574 a750fc0b j_mayer
GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5575 76a66253 j_mayer
/* nmacchws  - nmacchws.  */
5576 a750fc0b j_mayer
GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5577 76a66253 j_mayer
/* nmacchwso - nmacchwso. */
5578 a750fc0b j_mayer
GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5579 76a66253 j_mayer
/* nmachhw   - nmachhw.   */
5580 a750fc0b j_mayer
GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5581 76a66253 j_mayer
/* nmachhwo  - nmachhwo.  */
5582 a750fc0b j_mayer
GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5583 76a66253 j_mayer
/* nmachhws  - nmachhws.  */
5584 a750fc0b j_mayer
GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5585 76a66253 j_mayer
/* nmachhwso - nmachhwso. */
5586 a750fc0b j_mayer
GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5587 76a66253 j_mayer
/* nmaclhw   - nmaclhw.   */
5588 a750fc0b j_mayer
GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5589 76a66253 j_mayer
/* nmaclhwo  - nmaclhwo.  */
5590 a750fc0b j_mayer
GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5591 76a66253 j_mayer
/* nmaclhws  - nmaclhws.  */
5592 a750fc0b j_mayer
GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5593 76a66253 j_mayer
/* nmaclhwso - nmaclhwso. */
5594 a750fc0b j_mayer
GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5595 76a66253 j_mayer
5596 76a66253 j_mayer
/* mulchw  - mulchw.  */
5597 a750fc0b j_mayer
GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5598 76a66253 j_mayer
/* mulchwu - mulchwu. */
5599 a750fc0b j_mayer
GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5600 76a66253 j_mayer
/* mulhhw  - mulhhw.  */
5601 a750fc0b j_mayer
GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5602 76a66253 j_mayer
/* mulhhwu - mulhhwu. */
5603 a750fc0b j_mayer
GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5604 76a66253 j_mayer
/* mullhw  - mullhw.  */
5605 a750fc0b j_mayer
GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5606 76a66253 j_mayer
/* mullhwu - mullhwu. */
5607 a750fc0b j_mayer
GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5608 76a66253 j_mayer
5609 76a66253 j_mayer
/* mfdcr */
5610 05332d70 j_mayer
GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
5611 76a66253 j_mayer
{
5612 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5613 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
5614 76a66253 j_mayer
#else
5615 06dca6a7 aurel32
    TCGv dcrn;
5616 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5617 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
5618 76a66253 j_mayer
        return;
5619 76a66253 j_mayer
    }
5620 06dca6a7 aurel32
    /* NIP cannot be restored if the memory exception comes from an helper */
5621 06dca6a7 aurel32
    gen_update_nip(ctx, ctx->nip - 4);
5622 06dca6a7 aurel32
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5623 06dca6a7 aurel32
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
5624 06dca6a7 aurel32
    tcg_temp_free(dcrn);
5625 76a66253 j_mayer
#endif
5626 76a66253 j_mayer
}
5627 76a66253 j_mayer
5628 76a66253 j_mayer
/* mtdcr */
5629 05332d70 j_mayer
GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
5630 76a66253 j_mayer
{
5631 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5632 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
5633 76a66253 j_mayer
#else
5634 06dca6a7 aurel32
    TCGv dcrn;
5635 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5636 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
5637 76a66253 j_mayer
        return;
5638 76a66253 j_mayer
    }
5639 06dca6a7 aurel32
    /* NIP cannot be restored if the memory exception comes from an helper */
5640 06dca6a7 aurel32
    gen_update_nip(ctx, ctx->nip - 4);
5641 06dca6a7 aurel32
    dcrn = tcg_const_tl(SPR(ctx->opcode));
5642 06dca6a7 aurel32
    gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
5643 06dca6a7 aurel32
    tcg_temp_free(dcrn);
5644 a42bd6cc j_mayer
#endif
5645 a42bd6cc j_mayer
}
5646 a42bd6cc j_mayer
5647 a42bd6cc j_mayer
/* mfdcrx */
5648 2662a059 j_mayer
/* XXX: not implemented on 440 ? */
5649 05332d70 j_mayer
GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
5650 a42bd6cc j_mayer
{
5651 a42bd6cc j_mayer
#if defined(CONFIG_USER_ONLY)
5652 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
5653 a42bd6cc j_mayer
#else
5654 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5655 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
5656 a42bd6cc j_mayer
        return;
5657 a42bd6cc j_mayer
    }
5658 06dca6a7 aurel32
    /* NIP cannot be restored if the memory exception comes from an helper */
5659 06dca6a7 aurel32
    gen_update_nip(ctx, ctx->nip - 4);
5660 06dca6a7 aurel32
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5661 a750fc0b j_mayer
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5662 a42bd6cc j_mayer
#endif
5663 a42bd6cc j_mayer
}
5664 a42bd6cc j_mayer
5665 a42bd6cc j_mayer
/* mtdcrx */
5666 2662a059 j_mayer
/* XXX: not implemented on 440 ? */
5667 05332d70 j_mayer
GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
5668 a42bd6cc j_mayer
{
5669 a42bd6cc j_mayer
#if defined(CONFIG_USER_ONLY)
5670 e1833e1f j_mayer
    GEN_EXCP_PRIVREG(ctx);
5671 a42bd6cc j_mayer
#else
5672 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5673 e1833e1f j_mayer
        GEN_EXCP_PRIVREG(ctx);
5674 a42bd6cc j_mayer
        return;
5675 a42bd6cc j_mayer
    }
5676 06dca6a7 aurel32
    /* NIP cannot be restored if the memory exception comes from an helper */
5677 06dca6a7 aurel32
    gen_update_nip(ctx, ctx->nip - 4);
5678 06dca6a7 aurel32
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5679 a750fc0b j_mayer
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5680 76a66253 j_mayer
#endif
5681 76a66253 j_mayer
}
5682 76a66253 j_mayer
5683 a750fc0b j_mayer
/* mfdcrux (PPC 460) : user-mode access to DCR */
5684 a750fc0b j_mayer
GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
5685 a750fc0b j_mayer
{
5686 06dca6a7 aurel32
    /* NIP cannot be restored if the memory exception comes from an helper */
5687 06dca6a7 aurel32
    gen_update_nip(ctx, ctx->nip - 4);
5688 06dca6a7 aurel32
    gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5689 a750fc0b j_mayer
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5690 a750fc0b j_mayer
}
5691 a750fc0b j_mayer
5692 a750fc0b j_mayer
/* mtdcrux (PPC 460) : user-mode access to DCR */
5693 a750fc0b j_mayer
GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
5694 a750fc0b j_mayer
{
5695 06dca6a7 aurel32
    /* NIP cannot be restored if the memory exception comes from an helper */
5696 06dca6a7 aurel32
    gen_update_nip(ctx, ctx->nip - 4);
5697 06dca6a7 aurel32
    gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5698 a750fc0b j_mayer
    /* Note: Rc update flag set leads to undefined state of Rc0 */
5699 a750fc0b j_mayer
}
5700 a750fc0b j_mayer
5701 76a66253 j_mayer
/* dccci */
5702 76a66253 j_mayer
GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
5703 76a66253 j_mayer
{
5704 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5705 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5706 76a66253 j_mayer
#else
5707 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5708 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5709 76a66253 j_mayer
        return;
5710 76a66253 j_mayer
    }
5711 76a66253 j_mayer
    /* interpreted as no-op */
5712 76a66253 j_mayer
#endif
5713 76a66253 j_mayer
}
5714 76a66253 j_mayer
5715 76a66253 j_mayer
/* dcread */
5716 76a66253 j_mayer
GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
5717 76a66253 j_mayer
{
5718 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5719 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5720 76a66253 j_mayer
#else
5721 b61f2753 aurel32
    TCGv EA, val;
5722 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5723 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5724 76a66253 j_mayer
        return;
5725 76a66253 j_mayer
    }
5726 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_CACHE);
5727 a7812ae4 pbrook
    EA = tcg_temp_new();
5728 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);
5729 a7812ae4 pbrook
    val = tcg_temp_new();
5730 76db3ba4 aurel32
    gen_qemu_ld32u(ctx, val, EA);
5731 b61f2753 aurel32
    tcg_temp_free(val);
5732 b61f2753 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5733 b61f2753 aurel32
    tcg_temp_free(EA);
5734 76a66253 j_mayer
#endif
5735 76a66253 j_mayer
}
5736 76a66253 j_mayer
5737 76a66253 j_mayer
/* icbt */
5738 c7697e1f j_mayer
GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
5739 76a66253 j_mayer
{
5740 76a66253 j_mayer
    /* interpreted as no-op */
5741 76a66253 j_mayer
    /* XXX: specification say this is treated as a load by the MMU
5742 76a66253 j_mayer
     *      but does not generate any exception
5743 76a66253 j_mayer
     */
5744 76a66253 j_mayer
}
5745 76a66253 j_mayer
5746 76a66253 j_mayer
/* iccci */
5747 76a66253 j_mayer
GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
5748 76a66253 j_mayer
{
5749 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5750 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5751 76a66253 j_mayer
#else
5752 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5753 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5754 76a66253 j_mayer
        return;
5755 76a66253 j_mayer
    }
5756 76a66253 j_mayer
    /* interpreted as no-op */
5757 76a66253 j_mayer
#endif
5758 76a66253 j_mayer
}
5759 76a66253 j_mayer
5760 76a66253 j_mayer
/* icread */
5761 76a66253 j_mayer
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
5762 76a66253 j_mayer
{
5763 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5764 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5765 76a66253 j_mayer
#else
5766 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5767 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5768 76a66253 j_mayer
        return;
5769 76a66253 j_mayer
    }
5770 76a66253 j_mayer
    /* interpreted as no-op */
5771 76a66253 j_mayer
#endif
5772 76a66253 j_mayer
}
5773 76a66253 j_mayer
5774 76db3ba4 aurel32
/* rfci (mem_idx only) */
5775 c7697e1f j_mayer
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
5776 a42bd6cc j_mayer
{
5777 a42bd6cc j_mayer
#if defined(CONFIG_USER_ONLY)
5778 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5779 a42bd6cc j_mayer
#else
5780 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5781 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5782 a42bd6cc j_mayer
        return;
5783 a42bd6cc j_mayer
    }
5784 a42bd6cc j_mayer
    /* Restore CPU state */
5785 d72a19f7 aurel32
    gen_helper_40x_rfci();
5786 e1833e1f j_mayer
    GEN_SYNC(ctx);
5787 a42bd6cc j_mayer
#endif
5788 a42bd6cc j_mayer
}
5789 a42bd6cc j_mayer
5790 a42bd6cc j_mayer
GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
5791 a42bd6cc j_mayer
{
5792 a42bd6cc j_mayer
#if defined(CONFIG_USER_ONLY)
5793 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5794 a42bd6cc j_mayer
#else
5795 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5796 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5797 a42bd6cc j_mayer
        return;
5798 a42bd6cc j_mayer
    }
5799 a42bd6cc j_mayer
    /* Restore CPU state */
5800 d72a19f7 aurel32
    gen_helper_rfci();
5801 e1833e1f j_mayer
    GEN_SYNC(ctx);
5802 a42bd6cc j_mayer
#endif
5803 a42bd6cc j_mayer
}
5804 a42bd6cc j_mayer
5805 a42bd6cc j_mayer
/* BookE specific */
5806 2662a059 j_mayer
/* XXX: not implemented on 440 ? */
5807 05332d70 j_mayer
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
5808 76a66253 j_mayer
{
5809 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5810 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5811 76a66253 j_mayer
#else
5812 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5813 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5814 76a66253 j_mayer
        return;
5815 76a66253 j_mayer
    }
5816 76a66253 j_mayer
    /* Restore CPU state */
5817 d72a19f7 aurel32
    gen_helper_rfdi();
5818 e1833e1f j_mayer
    GEN_SYNC(ctx);
5819 76a66253 j_mayer
#endif
5820 76a66253 j_mayer
}
5821 76a66253 j_mayer
5822 2662a059 j_mayer
/* XXX: not implemented on 440 ? */
5823 a750fc0b j_mayer
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
5824 a42bd6cc j_mayer
{
5825 a42bd6cc j_mayer
#if defined(CONFIG_USER_ONLY)
5826 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5827 a42bd6cc j_mayer
#else
5828 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5829 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5830 a42bd6cc j_mayer
        return;
5831 a42bd6cc j_mayer
    }
5832 a42bd6cc j_mayer
    /* Restore CPU state */
5833 d72a19f7 aurel32
    gen_helper_rfmci();
5834 e1833e1f j_mayer
    GEN_SYNC(ctx);
5835 a42bd6cc j_mayer
#endif
5836 a42bd6cc j_mayer
}
5837 5eb7995e j_mayer
5838 d9bce9d9 j_mayer
/* TLB management - PowerPC 405 implementation */
5839 76a66253 j_mayer
/* tlbre */
5840 c7697e1f j_mayer
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
5841 76a66253 j_mayer
{
5842 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5843 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5844 76a66253 j_mayer
#else
5845 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5846 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5847 76a66253 j_mayer
        return;
5848 76a66253 j_mayer
    }
5849 76a66253 j_mayer
    switch (rB(ctx->opcode)) {
5850 76a66253 j_mayer
    case 0:
5851 74d37793 aurel32
        gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5852 76a66253 j_mayer
        break;
5853 76a66253 j_mayer
    case 1:
5854 74d37793 aurel32
        gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5855 76a66253 j_mayer
        break;
5856 76a66253 j_mayer
    default:
5857 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);
5858 76a66253 j_mayer
        break;
5859 9a64fbe4 bellard
    }
5860 76a66253 j_mayer
#endif
5861 76a66253 j_mayer
}
5862 76a66253 j_mayer
5863 d9bce9d9 j_mayer
/* tlbsx - tlbsx. */
5864 c7697e1f j_mayer
GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5865 76a66253 j_mayer
{
5866 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5867 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5868 76a66253 j_mayer
#else
5869 74d37793 aurel32
    TCGv t0;
5870 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5871 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5872 76a66253 j_mayer
        return;
5873 76a66253 j_mayer
    }
5874 74d37793 aurel32
    t0 = tcg_temp_new();
5875 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
5876 74d37793 aurel32
    gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5877 74d37793 aurel32
    tcg_temp_free(t0);
5878 74d37793 aurel32
    if (Rc(ctx->opcode)) {
5879 74d37793 aurel32
        int l1 = gen_new_label();
5880 74d37793 aurel32
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5881 74d37793 aurel32
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5882 74d37793 aurel32
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5883 74d37793 aurel32
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5884 74d37793 aurel32
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5885 74d37793 aurel32
        gen_set_label(l1);
5886 74d37793 aurel32
    }
5887 76a66253 j_mayer
#endif
5888 79aceca5 bellard
}
5889 79aceca5 bellard
5890 76a66253 j_mayer
/* tlbwe */
5891 c7697e1f j_mayer
GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
5892 79aceca5 bellard
{
5893 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
5894 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5895 76a66253 j_mayer
#else
5896 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5897 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5898 76a66253 j_mayer
        return;
5899 76a66253 j_mayer
    }
5900 76a66253 j_mayer
    switch (rB(ctx->opcode)) {
5901 76a66253 j_mayer
    case 0:
5902 74d37793 aurel32
        gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5903 76a66253 j_mayer
        break;
5904 76a66253 j_mayer
    case 1:
5905 74d37793 aurel32
        gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5906 76a66253 j_mayer
        break;
5907 76a66253 j_mayer
    default:
5908 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);
5909 76a66253 j_mayer
        break;
5910 9a64fbe4 bellard
    }
5911 76a66253 j_mayer
#endif
5912 76a66253 j_mayer
}
5913 76a66253 j_mayer
5914 a4bb6c3e j_mayer
/* TLB management - PowerPC 440 implementation */
5915 5eb7995e j_mayer
/* tlbre */
5916 c7697e1f j_mayer
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5917 5eb7995e j_mayer
{
5918 5eb7995e j_mayer
#if defined(CONFIG_USER_ONLY)
5919 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5920 5eb7995e j_mayer
#else
5921 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5922 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5923 5eb7995e j_mayer
        return;
5924 5eb7995e j_mayer
    }
5925 5eb7995e j_mayer
    switch (rB(ctx->opcode)) {
5926 5eb7995e j_mayer
    case 0:
5927 5eb7995e j_mayer
    case 1:
5928 5eb7995e j_mayer
    case 2:
5929 74d37793 aurel32
        {
5930 74d37793 aurel32
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5931 74d37793 aurel32
            gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5932 74d37793 aurel32
            tcg_temp_free_i32(t0);
5933 74d37793 aurel32
        }
5934 5eb7995e j_mayer
        break;
5935 5eb7995e j_mayer
    default:
5936 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);
5937 5eb7995e j_mayer
        break;
5938 5eb7995e j_mayer
    }
5939 5eb7995e j_mayer
#endif
5940 5eb7995e j_mayer
}
5941 5eb7995e j_mayer
5942 5eb7995e j_mayer
/* tlbsx - tlbsx. */
5943 c7697e1f j_mayer
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5944 5eb7995e j_mayer
{
5945 5eb7995e j_mayer
#if defined(CONFIG_USER_ONLY)
5946 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5947 5eb7995e j_mayer
#else
5948 74d37793 aurel32
    TCGv t0;
5949 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5950 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5951 5eb7995e j_mayer
        return;
5952 5eb7995e j_mayer
    }
5953 74d37793 aurel32
    t0 = tcg_temp_new();
5954 76db3ba4 aurel32
    gen_addr_reg_index(ctx, t0);
5955 74d37793 aurel32
    gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5956 74d37793 aurel32
    tcg_temp_free(t0);
5957 74d37793 aurel32
    if (Rc(ctx->opcode)) {
5958 74d37793 aurel32
        int l1 = gen_new_label();
5959 74d37793 aurel32
        tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5960 74d37793 aurel32
        tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5961 74d37793 aurel32
        tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5962 74d37793 aurel32
        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5963 74d37793 aurel32
        tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5964 74d37793 aurel32
        gen_set_label(l1);
5965 74d37793 aurel32
    }
5966 5eb7995e j_mayer
#endif
5967 5eb7995e j_mayer
}
5968 5eb7995e j_mayer
5969 5eb7995e j_mayer
/* tlbwe */
5970 c7697e1f j_mayer
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5971 5eb7995e j_mayer
{
5972 5eb7995e j_mayer
#if defined(CONFIG_USER_ONLY)
5973 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
5974 5eb7995e j_mayer
#else
5975 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
5976 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
5977 5eb7995e j_mayer
        return;
5978 5eb7995e j_mayer
    }
5979 5eb7995e j_mayer
    switch (rB(ctx->opcode)) {
5980 5eb7995e j_mayer
    case 0:
5981 5eb7995e j_mayer
    case 1:
5982 5eb7995e j_mayer
    case 2:
5983 74d37793 aurel32
        {
5984 74d37793 aurel32
            TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5985 74d37793 aurel32
            gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5986 74d37793 aurel32
            tcg_temp_free_i32(t0);
5987 74d37793 aurel32
        }
5988 5eb7995e j_mayer
        break;
5989 5eb7995e j_mayer
    default:
5990 e1833e1f j_mayer
        GEN_EXCP_INVAL(ctx);
5991 5eb7995e j_mayer
        break;
5992 5eb7995e j_mayer
    }
5993 5eb7995e j_mayer
#endif
5994 5eb7995e j_mayer
}
5995 5eb7995e j_mayer
5996 76a66253 j_mayer
/* wrtee */
5997 05332d70 j_mayer
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
5998 76a66253 j_mayer
{
5999 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
6000 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
6001 76a66253 j_mayer
#else
6002 6527f6ea aurel32
    TCGv t0;
6003 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
6004 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
6005 76a66253 j_mayer
        return;
6006 76a66253 j_mayer
    }
6007 6527f6ea aurel32
    t0 = tcg_temp_new();
6008 6527f6ea aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6009 6527f6ea aurel32
    tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6010 6527f6ea aurel32
    tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6011 6527f6ea aurel32
    tcg_temp_free(t0);
6012 dee96f6c j_mayer
    /* Stop translation to have a chance to raise an exception
6013 dee96f6c j_mayer
     * if we just set msr_ee to 1
6014 dee96f6c j_mayer
     */
6015 e1833e1f j_mayer
    GEN_STOP(ctx);
6016 76a66253 j_mayer
#endif
6017 76a66253 j_mayer
}
6018 76a66253 j_mayer
6019 76a66253 j_mayer
/* wrteei */
6020 05332d70 j_mayer
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
6021 76a66253 j_mayer
{
6022 76a66253 j_mayer
#if defined(CONFIG_USER_ONLY)
6023 e1833e1f j_mayer
    GEN_EXCP_PRIVOPC(ctx);
6024 76a66253 j_mayer
#else
6025 76db3ba4 aurel32
    if (unlikely(!ctx->mem_idx)) {
6026 e1833e1f j_mayer
        GEN_EXCP_PRIVOPC(ctx);
6027 76a66253 j_mayer
        return;
6028 76a66253 j_mayer
    }
6029 6527f6ea aurel32
    if (ctx->opcode & 0x00010000) {
6030 6527f6ea aurel32
        tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6031 6527f6ea aurel32
        /* Stop translation to have a chance to raise an exception */
6032 6527f6ea aurel32
        GEN_STOP(ctx);
6033 6527f6ea aurel32
    } else {
6034 6527f6ea aurel32
        tcg_gen_andi_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6035 6527f6ea aurel32
    }
6036 76a66253 j_mayer
#endif
6037 76a66253 j_mayer
}
6038 76a66253 j_mayer
6039 08e46e54 j_mayer
/* PowerPC 440 specific instructions */
6040 76a66253 j_mayer
/* dlmzb */
6041 76a66253 j_mayer
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
6042 76a66253 j_mayer
{
6043 ef0d51af aurel32
    TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6044 ef0d51af aurel32
    gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
6045 ef0d51af aurel32
                     cpu_gpr[rB(ctx->opcode)], t0);
6046 ef0d51af aurel32
    tcg_temp_free_i32(t0);
6047 76a66253 j_mayer
}
6048 76a66253 j_mayer
6049 76a66253 j_mayer
/* mbar replaces eieio on 440 */
6050 76a66253 j_mayer
GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
6051 76a66253 j_mayer
{
6052 76a66253 j_mayer
    /* interpreted as no-op */
6053 76a66253 j_mayer
}
6054 76a66253 j_mayer
6055 76a66253 j_mayer
/* msync replaces sync on 440 */
6056 0db1b20e j_mayer
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
6057 76a66253 j_mayer
{
6058 76a66253 j_mayer
    /* interpreted as no-op */
6059 76a66253 j_mayer
}
6060 76a66253 j_mayer
6061 76a66253 j_mayer
/* icbt */
6062 c7697e1f j_mayer
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
6063 76a66253 j_mayer
{
6064 76a66253 j_mayer
    /* interpreted as no-op */
6065 76a66253 j_mayer
    /* XXX: specification say this is treated as a load by the MMU
6066 76a66253 j_mayer
     *      but does not generate any exception
6067 76a66253 j_mayer
     */
6068 79aceca5 bellard
}
6069 79aceca5 bellard
6070 a9d9eb8f j_mayer
/***                      Altivec vector extension                         ***/
6071 a9d9eb8f j_mayer
/* Altivec registers moves */
6072 a9d9eb8f j_mayer
6073 a9d9eb8f j_mayer
#define GEN_VR_LDX(name, opc2, opc3)                                          \
6074 fe1e5c53 aurel32
GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)                  \
6075 a9d9eb8f j_mayer
{                                                                             \
6076 fe1e5c53 aurel32
    TCGv EA;                                                                  \
6077 a9d9eb8f j_mayer
    if (unlikely(!ctx->altivec_enabled)) {                                    \
6078 a9d9eb8f j_mayer
        GEN_EXCP_NO_VR(ctx);                                                  \
6079 a9d9eb8f j_mayer
        return;                                                               \
6080 a9d9eb8f j_mayer
    }                                                                         \
6081 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6082 fe1e5c53 aurel32
    EA = tcg_temp_new();                                                      \
6083 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
6084 fe1e5c53 aurel32
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6085 76db3ba4 aurel32
    if (ctx->le_mode) {                                                       \
6086 76db3ba4 aurel32
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6087 fe1e5c53 aurel32
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6088 76db3ba4 aurel32
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6089 fe1e5c53 aurel32
    } else {                                                                  \
6090 76db3ba4 aurel32
        gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6091 fe1e5c53 aurel32
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6092 76db3ba4 aurel32
        gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6093 fe1e5c53 aurel32
    }                                                                         \
6094 fe1e5c53 aurel32
    tcg_temp_free(EA);                                                        \
6095 a9d9eb8f j_mayer
}
6096 a9d9eb8f j_mayer
6097 a9d9eb8f j_mayer
#define GEN_VR_STX(name, opc2, opc3)                                          \
6098 a9d9eb8f j_mayer
GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)              \
6099 a9d9eb8f j_mayer
{                                                                             \
6100 fe1e5c53 aurel32
    TCGv EA;                                                                  \
6101 a9d9eb8f j_mayer
    if (unlikely(!ctx->altivec_enabled)) {                                    \
6102 a9d9eb8f j_mayer
        GEN_EXCP_NO_VR(ctx);                                                  \
6103 a9d9eb8f j_mayer
        return;                                                               \
6104 a9d9eb8f j_mayer
    }                                                                         \
6105 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
6106 fe1e5c53 aurel32
    EA = tcg_temp_new();                                                      \
6107 76db3ba4 aurel32
    gen_addr_reg_index(ctx, EA);                                              \
6108 fe1e5c53 aurel32
    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
6109 76db3ba4 aurel32
    if (ctx->le_mode) {                                                       \
6110 76db3ba4 aurel32
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6111 fe1e5c53 aurel32
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6112 76db3ba4 aurel32
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6113 fe1e5c53 aurel32
    } else {                                                                  \
6114 76db3ba4 aurel32
        gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                    \
6115 fe1e5c53 aurel32
        tcg_gen_addi_tl(EA, EA, 8);                                           \
6116 76db3ba4 aurel32
        gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                    \
6117 fe1e5c53 aurel32
    }                                                                         \
6118 fe1e5c53 aurel32
    tcg_temp_free(EA);                                                        \
6119 a9d9eb8f j_mayer
}
6120 a9d9eb8f j_mayer
6121 fe1e5c53 aurel32
GEN_VR_LDX(lvx, 0x07, 0x03);
6122 a9d9eb8f j_mayer
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
6123 fe1e5c53 aurel32
GEN_VR_LDX(lvxl, 0x07, 0x0B);
6124 a9d9eb8f j_mayer
6125 fe1e5c53 aurel32
GEN_VR_STX(svx, 0x07, 0x07);
6126 a9d9eb8f j_mayer
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
6127 fe1e5c53 aurel32
GEN_VR_STX(svxl, 0x07, 0x0F);
6128 a9d9eb8f j_mayer
6129 0487d6a8 j_mayer
/***                           SPE extension                               ***/
6130 0487d6a8 j_mayer
/* Register moves */
6131 3cd7d1dd j_mayer
6132 a7812ae4 pbrook
static always_inline void gen_load_gpr64(TCGv_i64 t, int reg) {
6133 f78fb44e aurel32
#if defined(TARGET_PPC64)
6134 f78fb44e aurel32
    tcg_gen_mov_i64(t, cpu_gpr[reg]);
6135 f78fb44e aurel32
#else
6136 36aa55dc pbrook
    tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
6137 3cd7d1dd j_mayer
#endif
6138 f78fb44e aurel32
}
6139 3cd7d1dd j_mayer
6140 a7812ae4 pbrook
static always_inline void gen_store_gpr64(int reg, TCGv_i64 t) {
6141 f78fb44e aurel32
#if defined(TARGET_PPC64)
6142 f78fb44e aurel32
    tcg_gen_mov_i64(cpu_gpr[reg], t);
6143 f78fb44e aurel32
#else
6144 a7812ae4 pbrook
    TCGv_i64 tmp = tcg_temp_new_i64();
6145 f78fb44e aurel32
    tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
6146 f78fb44e aurel32
    tcg_gen_shri_i64(tmp, t, 32);
6147 f78fb44e aurel32
    tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
6148 a7812ae4 pbrook
    tcg_temp_free_i64(tmp);
6149 3cd7d1dd j_mayer
#endif
6150 f78fb44e aurel32
}
6151 3cd7d1dd j_mayer
6152 0487d6a8 j_mayer
#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
6153 0487d6a8 j_mayer
GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)                   \
6154 0487d6a8 j_mayer
{                                                                             \
6155 0487d6a8 j_mayer
    if (Rc(ctx->opcode))                                                      \
6156 0487d6a8 j_mayer
        gen_##name1(ctx);                                                     \
6157 0487d6a8 j_mayer
    else                                                                      \
6158 0487d6a8 j_mayer
        gen_##name0(ctx);                                                     \
6159 0487d6a8 j_mayer
}
6160 0487d6a8 j_mayer
6161 0487d6a8 j_mayer
/* Handler for undefined SPE opcodes */
6162 b068d6a7 j_mayer
static always_inline void gen_speundef (DisasContext *ctx)
6163 0487d6a8 j_mayer
{
6164 e1833e1f j_mayer
    GEN_EXCP_INVAL(ctx);
6165 0487d6a8 j_mayer
}
6166 0487d6a8 j_mayer
6167 57951c27 aurel32
/* SPE logic */
6168 57951c27 aurel32
#if defined(TARGET_PPC64)
6169 57951c27 aurel32
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
6170 b068d6a7 j_mayer
static always_inline void gen_##name (DisasContext *ctx)                      \
6171 0487d6a8 j_mayer
{                                                                             \
6172 0487d6a8 j_mayer
    if (unlikely(!ctx->spe_enabled)) {                                        \
6173 e1833e1f j_mayer
        GEN_EXCP_NO_AP(ctx);                                                  \
6174 0487d6a8 j_mayer
        return;                                                               \
6175 0487d6a8 j_mayer
    }                                                                         \
6176 57951c27 aurel32
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
6177 57951c27 aurel32
           cpu_gpr[rB(ctx->opcode)]);                                         \
6178 57951c27 aurel32
}
6179 57951c27 aurel32
#else
6180 57951c27 aurel32
#define GEN_SPEOP_LOGIC2(name, tcg_op)                                        \
6181 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6182 57951c27 aurel32
{                                                                             \
6183 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6184 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6185 57951c27 aurel32
        return;                                                               \
6186 57951c27 aurel32
    }                                                                         \
6187 57951c27 aurel32
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
6188 57951c27 aurel32
           cpu_gpr[rB(ctx->opcode)]);                                         \
6189 57951c27 aurel32
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
6190 57951c27 aurel32
           cpu_gprh[rB(ctx->opcode)]);                                        \
6191 0487d6a8 j_mayer
}
6192 57951c27 aurel32
#endif
6193 57951c27 aurel32
6194 57951c27 aurel32
GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6195 57951c27 aurel32
GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6196 57951c27 aurel32
GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6197 57951c27 aurel32
GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6198 57951c27 aurel32
GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6199 57951c27 aurel32
GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6200 57951c27 aurel32
GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6201 57951c27 aurel32
GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
6202 0487d6a8 j_mayer
6203 57951c27 aurel32
/* SPE logic immediate */
6204 57951c27 aurel32
#if defined(TARGET_PPC64)
6205 57951c27 aurel32
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
6206 3d3a6a0a aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6207 3d3a6a0a aurel32
{                                                                             \
6208 3d3a6a0a aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6209 3d3a6a0a aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6210 3d3a6a0a aurel32
        return;                                                               \
6211 3d3a6a0a aurel32
    }                                                                         \
6212 a7812ae4 pbrook
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6213 a7812ae4 pbrook
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6214 a7812ae4 pbrook
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6215 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6216 57951c27 aurel32
    tcg_opi(t0, t0, rB(ctx->opcode));                                         \
6217 57951c27 aurel32
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
6218 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6219 a7812ae4 pbrook
    tcg_temp_free_i64(t2);                                                    \
6220 57951c27 aurel32
    tcg_opi(t1, t1, rB(ctx->opcode));                                         \
6221 57951c27 aurel32
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6222 a7812ae4 pbrook
    tcg_temp_free_i32(t0);                                                    \
6223 a7812ae4 pbrook
    tcg_temp_free_i32(t1);                                                    \
6224 3d3a6a0a aurel32
}
6225 57951c27 aurel32
#else
6226 57951c27 aurel32
#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi)                               \
6227 b068d6a7 j_mayer
static always_inline void gen_##name (DisasContext *ctx)                      \
6228 0487d6a8 j_mayer
{                                                                             \
6229 0487d6a8 j_mayer
    if (unlikely(!ctx->spe_enabled)) {                                        \
6230 e1833e1f j_mayer
        GEN_EXCP_NO_AP(ctx);                                                  \
6231 0487d6a8 j_mayer
        return;                                                               \
6232 0487d6a8 j_mayer
    }                                                                         \
6233 57951c27 aurel32
    tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],               \
6234 57951c27 aurel32
            rB(ctx->opcode));                                                 \
6235 57951c27 aurel32
    tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],             \
6236 57951c27 aurel32
            rB(ctx->opcode));                                                 \
6237 0487d6a8 j_mayer
}
6238 57951c27 aurel32
#endif
6239 57951c27 aurel32
GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
6240 57951c27 aurel32
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
6241 57951c27 aurel32
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
6242 57951c27 aurel32
GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
6243 0487d6a8 j_mayer
6244 57951c27 aurel32
/* SPE arithmetic */
6245 57951c27 aurel32
#if defined(TARGET_PPC64)
6246 57951c27 aurel32
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6247 b068d6a7 j_mayer
static always_inline void gen_##name (DisasContext *ctx)                      \
6248 0487d6a8 j_mayer
{                                                                             \
6249 0487d6a8 j_mayer
    if (unlikely(!ctx->spe_enabled)) {                                        \
6250 e1833e1f j_mayer
        GEN_EXCP_NO_AP(ctx);                                                  \
6251 0487d6a8 j_mayer
        return;                                                               \
6252 0487d6a8 j_mayer
    }                                                                         \
6253 a7812ae4 pbrook
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6254 a7812ae4 pbrook
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6255 a7812ae4 pbrook
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6256 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6257 57951c27 aurel32
    tcg_op(t0, t0);                                                           \
6258 57951c27 aurel32
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
6259 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6260 a7812ae4 pbrook
    tcg_temp_free_i64(t2);                                                    \
6261 57951c27 aurel32
    tcg_op(t1, t1);                                                           \
6262 57951c27 aurel32
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6263 a7812ae4 pbrook
    tcg_temp_free_i32(t0);                                                    \
6264 a7812ae4 pbrook
    tcg_temp_free_i32(t1);                                                    \
6265 0487d6a8 j_mayer
}
6266 57951c27 aurel32
#else
6267 a7812ae4 pbrook
#define GEN_SPEOP_ARITH1(name, tcg_op)                                        \
6268 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6269 57951c27 aurel32
{                                                                             \
6270 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6271 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6272 57951c27 aurel32
        return;                                                               \
6273 57951c27 aurel32
    }                                                                         \
6274 57951c27 aurel32
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);               \
6275 57951c27 aurel32
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);             \
6276 57951c27 aurel32
}
6277 57951c27 aurel32
#endif
6278 0487d6a8 j_mayer
6279 a7812ae4 pbrook
static always_inline void gen_op_evabs (TCGv_i32 ret, TCGv_i32 arg1)
6280 57951c27 aurel32
{
6281 57951c27 aurel32
    int l1 = gen_new_label();
6282 57951c27 aurel32
    int l2 = gen_new_label();
6283 0487d6a8 j_mayer
6284 57951c27 aurel32
    tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6285 57951c27 aurel32
    tcg_gen_neg_i32(ret, arg1);
6286 57951c27 aurel32
    tcg_gen_br(l2);
6287 57951c27 aurel32
    gen_set_label(l1);
6288 a7812ae4 pbrook
    tcg_gen_mov_i32(ret, arg1);
6289 57951c27 aurel32
    gen_set_label(l2);
6290 57951c27 aurel32
}
6291 57951c27 aurel32
GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6292 57951c27 aurel32
GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6293 57951c27 aurel32
GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6294 57951c27 aurel32
GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
6295 a7812ae4 pbrook
static always_inline void gen_op_evrndw (TCGv_i32 ret, TCGv_i32 arg1)
6296 0487d6a8 j_mayer
{
6297 57951c27 aurel32
    tcg_gen_addi_i32(ret, arg1, 0x8000);
6298 57951c27 aurel32
    tcg_gen_ext16u_i32(ret, ret);
6299 57951c27 aurel32
}
6300 57951c27 aurel32
GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
6301 a7812ae4 pbrook
GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6302 a7812ae4 pbrook
GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
6303 0487d6a8 j_mayer
6304 57951c27 aurel32
#if defined(TARGET_PPC64)
6305 57951c27 aurel32
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
6306 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6307 0487d6a8 j_mayer
{                                                                             \
6308 0487d6a8 j_mayer
    if (unlikely(!ctx->spe_enabled)) {                                        \
6309 e1833e1f j_mayer
        GEN_EXCP_NO_AP(ctx);                                                  \
6310 0487d6a8 j_mayer
        return;                                                               \
6311 0487d6a8 j_mayer
    }                                                                         \
6312 a7812ae4 pbrook
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6313 a7812ae4 pbrook
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6314 a7812ae4 pbrook
    TCGv_i32 t2 = tcg_temp_local_new_i32();                                   \
6315 a7812ae4 pbrook
    TCGv_i64 t3 = tcg_temp_local_new(TCG_TYPE_I64);                           \
6316 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6317 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]);                      \
6318 57951c27 aurel32
    tcg_op(t0, t0, t2);                                                       \
6319 57951c27 aurel32
    tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32);                       \
6320 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t1, t3);                                            \
6321 57951c27 aurel32
    tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32);                       \
6322 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t2, t3);                                            \
6323 a7812ae4 pbrook
    tcg_temp_free_i64(t3);                                                    \
6324 57951c27 aurel32
    tcg_op(t1, t1, t2);                                                       \
6325 a7812ae4 pbrook
    tcg_temp_free_i32(t2);                                                    \
6326 57951c27 aurel32
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6327 a7812ae4 pbrook
    tcg_temp_free_i32(t0);                                                    \
6328 a7812ae4 pbrook
    tcg_temp_free_i32(t1);                                                    \
6329 0487d6a8 j_mayer
}
6330 57951c27 aurel32
#else
6331 57951c27 aurel32
#define GEN_SPEOP_ARITH2(name, tcg_op)                                        \
6332 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6333 0487d6a8 j_mayer
{                                                                             \
6334 0487d6a8 j_mayer
    if (unlikely(!ctx->spe_enabled)) {                                        \
6335 e1833e1f j_mayer
        GEN_EXCP_NO_AP(ctx);                                                  \
6336 0487d6a8 j_mayer
        return;                                                               \
6337 0487d6a8 j_mayer
    }                                                                         \
6338 57951c27 aurel32
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],                \
6339 57951c27 aurel32
           cpu_gpr[rB(ctx->opcode)]);                                         \
6340 57951c27 aurel32
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],              \
6341 57951c27 aurel32
           cpu_gprh[rB(ctx->opcode)]);                                        \
6342 0487d6a8 j_mayer
}
6343 57951c27 aurel32
#endif
6344 0487d6a8 j_mayer
6345 a7812ae4 pbrook
static always_inline void gen_op_evsrwu (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6346 57951c27 aurel32
{
6347 a7812ae4 pbrook
    TCGv_i32 t0;
6348 57951c27 aurel32
    int l1, l2;
6349 0487d6a8 j_mayer
6350 57951c27 aurel32
    l1 = gen_new_label();
6351 57951c27 aurel32
    l2 = gen_new_label();
6352 a7812ae4 pbrook
    t0 = tcg_temp_local_new_i32();
6353 57951c27 aurel32
    /* No error here: 6 bits are used */
6354 57951c27 aurel32
    tcg_gen_andi_i32(t0, arg2, 0x3F);
6355 57951c27 aurel32
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6356 57951c27 aurel32
    tcg_gen_shr_i32(ret, arg1, t0);
6357 57951c27 aurel32
    tcg_gen_br(l2);
6358 57951c27 aurel32
    gen_set_label(l1);
6359 57951c27 aurel32
    tcg_gen_movi_i32(ret, 0);
6360 57951c27 aurel32
    tcg_gen_br(l2);
6361 a7812ae4 pbrook
    tcg_temp_free_i32(t0);
6362 57951c27 aurel32
}
6363 57951c27 aurel32
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
6364 a7812ae4 pbrook
static always_inline void gen_op_evsrws (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6365 57951c27 aurel32
{
6366 a7812ae4 pbrook
    TCGv_i32 t0;
6367 57951c27 aurel32
    int l1, l2;
6368 57951c27 aurel32
6369 57951c27 aurel32
    l1 = gen_new_label();
6370 57951c27 aurel32
    l2 = gen_new_label();
6371 a7812ae4 pbrook
    t0 = tcg_temp_local_new_i32();
6372 57951c27 aurel32
    /* No error here: 6 bits are used */
6373 57951c27 aurel32
    tcg_gen_andi_i32(t0, arg2, 0x3F);
6374 57951c27 aurel32
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6375 57951c27 aurel32
    tcg_gen_sar_i32(ret, arg1, t0);
6376 57951c27 aurel32
    tcg_gen_br(l2);
6377 57951c27 aurel32
    gen_set_label(l1);
6378 57951c27 aurel32
    tcg_gen_movi_i32(ret, 0);
6379 57951c27 aurel32
    tcg_gen_br(l2);
6380 a7812ae4 pbrook
    tcg_temp_free_i32(t0);
6381 57951c27 aurel32
}
6382 57951c27 aurel32
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
6383 a7812ae4 pbrook
static always_inline void gen_op_evslw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6384 57951c27 aurel32
{
6385 a7812ae4 pbrook
    TCGv_i32 t0;
6386 57951c27 aurel32
    int l1, l2;
6387 57951c27 aurel32
6388 57951c27 aurel32
    l1 = gen_new_label();
6389 57951c27 aurel32
    l2 = gen_new_label();
6390 a7812ae4 pbrook
    t0 = tcg_temp_local_new_i32();
6391 57951c27 aurel32
    /* No error here: 6 bits are used */
6392 57951c27 aurel32
    tcg_gen_andi_i32(t0, arg2, 0x3F);
6393 57951c27 aurel32
    tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6394 57951c27 aurel32
    tcg_gen_shl_i32(ret, arg1, t0);
6395 57951c27 aurel32
    tcg_gen_br(l2);
6396 57951c27 aurel32
    gen_set_label(l1);
6397 57951c27 aurel32
    tcg_gen_movi_i32(ret, 0);
6398 57951c27 aurel32
    tcg_gen_br(l2);
6399 a7812ae4 pbrook
    tcg_temp_free_i32(t0);
6400 57951c27 aurel32
}
6401 57951c27 aurel32
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
6402 a7812ae4 pbrook
static always_inline void gen_op_evrlw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6403 57951c27 aurel32
{
6404 a7812ae4 pbrook
    TCGv_i32 t0 = tcg_temp_new_i32();
6405 57951c27 aurel32
    tcg_gen_andi_i32(t0, arg2, 0x1F);
6406 57951c27 aurel32
    tcg_gen_rotl_i32(ret, arg1, t0);
6407 a7812ae4 pbrook
    tcg_temp_free_i32(t0);
6408 57951c27 aurel32
}
6409 57951c27 aurel32
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
6410 57951c27 aurel32
static always_inline void gen_evmergehi (DisasContext *ctx)
6411 57951c27 aurel32
{
6412 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {
6413 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);
6414 57951c27 aurel32
        return;
6415 57951c27 aurel32
    }
6416 57951c27 aurel32
#if defined(TARGET_PPC64)
6417 a7812ae4 pbrook
    TCGv t0 = tcg_temp_new();
6418 a7812ae4 pbrook
    TCGv t1 = tcg_temp_new();
6419 57951c27 aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6420 57951c27 aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6421 57951c27 aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6422 57951c27 aurel32
    tcg_temp_free(t0);
6423 57951c27 aurel32
    tcg_temp_free(t1);
6424 57951c27 aurel32
#else
6425 57951c27 aurel32
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6426 57951c27 aurel32
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6427 57951c27 aurel32
#endif
6428 57951c27 aurel32
}
6429 57951c27 aurel32
GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
6430 a7812ae4 pbrook
static always_inline void gen_op_evsubf (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
6431 0487d6a8 j_mayer
{
6432 57951c27 aurel32
    tcg_gen_sub_i32(ret, arg2, arg1);
6433 57951c27 aurel32
}
6434 57951c27 aurel32
GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
6435 0487d6a8 j_mayer
6436 57951c27 aurel32
/* SPE arithmetic immediate */
6437 57951c27 aurel32
#if defined(TARGET_PPC64)
6438 57951c27 aurel32
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
6439 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6440 57951c27 aurel32
{                                                                             \
6441 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6442 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6443 57951c27 aurel32
        return;                                                               \
6444 57951c27 aurel32
    }                                                                         \
6445 a7812ae4 pbrook
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6446 a7812ae4 pbrook
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6447 a7812ae4 pbrook
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6448 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]);                      \
6449 57951c27 aurel32
    tcg_op(t0, t0, rA(ctx->opcode));                                          \
6450 57951c27 aurel32
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
6451 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6452 a7812ae4 pbrook
    tcg_temp_free_i64(t2);                                                        \
6453 57951c27 aurel32
    tcg_op(t1, t1, rA(ctx->opcode));                                          \
6454 57951c27 aurel32
    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);                 \
6455 a7812ae4 pbrook
    tcg_temp_free_i32(t0);                                                    \
6456 a7812ae4 pbrook
    tcg_temp_free_i32(t1);                                                    \
6457 57951c27 aurel32
}
6458 57951c27 aurel32
#else
6459 57951c27 aurel32
#define GEN_SPEOP_ARITH_IMM2(name, tcg_op)                                    \
6460 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6461 57951c27 aurel32
{                                                                             \
6462 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6463 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6464 57951c27 aurel32
        return;                                                               \
6465 57951c27 aurel32
    }                                                                         \
6466 57951c27 aurel32
    tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],                \
6467 57951c27 aurel32
           rA(ctx->opcode));                                                  \
6468 57951c27 aurel32
    tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)],              \
6469 57951c27 aurel32
           rA(ctx->opcode));                                                  \
6470 57951c27 aurel32
}
6471 57951c27 aurel32
#endif
6472 57951c27 aurel32
GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
6473 57951c27 aurel32
GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
6474 57951c27 aurel32
6475 57951c27 aurel32
/* SPE comparison */
6476 57951c27 aurel32
#if defined(TARGET_PPC64)
6477 57951c27 aurel32
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
6478 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6479 57951c27 aurel32
{                                                                             \
6480 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6481 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6482 57951c27 aurel32
        return;                                                               \
6483 57951c27 aurel32
    }                                                                         \
6484 57951c27 aurel32
    int l1 = gen_new_label();                                                 \
6485 57951c27 aurel32
    int l2 = gen_new_label();                                                 \
6486 57951c27 aurel32
    int l3 = gen_new_label();                                                 \
6487 57951c27 aurel32
    int l4 = gen_new_label();                                                 \
6488 a7812ae4 pbrook
    TCGv_i32 t0 = tcg_temp_local_new_i32();                                   \
6489 a7812ae4 pbrook
    TCGv_i32 t1 = tcg_temp_local_new_i32();                                   \
6490 a7812ae4 pbrook
    TCGv_i64 t2 = tcg_temp_local_new_i64();                                   \
6491 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]);                      \
6492 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]);                      \
6493 57951c27 aurel32
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l1);                                 \
6494 a7812ae4 pbrook
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0);                          \
6495 57951c27 aurel32
    tcg_gen_br(l2);                                                           \
6496 57951c27 aurel32
    gen_set_label(l1);                                                        \
6497 57951c27 aurel32
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
6498 57951c27 aurel32
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
6499 57951c27 aurel32
    gen_set_label(l2);                                                        \
6500 57951c27 aurel32
    tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32);                       \
6501 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t0, t2);                                            \
6502 57951c27 aurel32
    tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32);                       \
6503 57951c27 aurel32
    tcg_gen_trunc_i64_i32(t1, t2);                                            \
6504 a7812ae4 pbrook
    tcg_temp_free_i64(t2);                                                    \
6505 57951c27 aurel32
    tcg_gen_brcond_i32(tcg_cond, t0, t1, l3);                                 \
6506 57951c27 aurel32
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
6507 57951c27 aurel32
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
6508 57951c27 aurel32
    tcg_gen_br(l4);                                                           \
6509 57951c27 aurel32
    gen_set_label(l3);                                                        \
6510 57951c27 aurel32
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
6511 57951c27 aurel32
                    CRF_CH | CRF_CH_OR_CL);                                   \
6512 57951c27 aurel32
    gen_set_label(l4);                                                        \
6513 a7812ae4 pbrook
    tcg_temp_free_i32(t0);                                                    \
6514 a7812ae4 pbrook
    tcg_temp_free_i32(t1);                                                    \
6515 57951c27 aurel32
}
6516 57951c27 aurel32
#else
6517 57951c27 aurel32
#define GEN_SPEOP_COMP(name, tcg_cond)                                        \
6518 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6519 57951c27 aurel32
{                                                                             \
6520 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6521 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6522 57951c27 aurel32
        return;                                                               \
6523 57951c27 aurel32
    }                                                                         \
6524 57951c27 aurel32
    int l1 = gen_new_label();                                                 \
6525 57951c27 aurel32
    int l2 = gen_new_label();                                                 \
6526 57951c27 aurel32
    int l3 = gen_new_label();                                                 \
6527 57951c27 aurel32
    int l4 = gen_new_label();                                                 \
6528 57951c27 aurel32
                                                                              \
6529 57951c27 aurel32
    tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)],                    \
6530 57951c27 aurel32
                       cpu_gpr[rB(ctx->opcode)], l1);                         \
6531 57951c27 aurel32
    tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0);                           \
6532 57951c27 aurel32
    tcg_gen_br(l2);                                                           \
6533 57951c27 aurel32
    gen_set_label(l1);                                                        \
6534 57951c27 aurel32
    tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)],                              \
6535 57951c27 aurel32
                     CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL);                  \
6536 57951c27 aurel32
    gen_set_label(l2);                                                        \
6537 57951c27 aurel32
    tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)],                   \
6538 57951c27 aurel32
                       cpu_gprh[rB(ctx->opcode)], l3);                        \
6539 57951c27 aurel32
    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],  \
6540 57951c27 aurel32
                     ~(CRF_CH | CRF_CH_AND_CL));                              \
6541 57951c27 aurel32
    tcg_gen_br(l4);                                                           \
6542 57951c27 aurel32
    gen_set_label(l3);                                                        \
6543 57951c27 aurel32
    tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],   \
6544 57951c27 aurel32
                    CRF_CH | CRF_CH_OR_CL);                                   \
6545 57951c27 aurel32
    gen_set_label(l4);                                                        \
6546 57951c27 aurel32
}
6547 57951c27 aurel32
#endif
6548 57951c27 aurel32
GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
6549 57951c27 aurel32
GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
6550 57951c27 aurel32
GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
6551 57951c27 aurel32
GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
6552 57951c27 aurel32
GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
6553 57951c27 aurel32
6554 57951c27 aurel32
/* SPE misc */
6555 57951c27 aurel32
static always_inline void gen_brinc (DisasContext *ctx)
6556 57951c27 aurel32
{
6557 57951c27 aurel32
    /* Note: brinc is usable even if SPE is disabled */
6558 a7812ae4 pbrook
    gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
6559 a7812ae4 pbrook
                     cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6560 0487d6a8 j_mayer
}
6561 57951c27 aurel32
static always_inline void gen_evmergelo (DisasContext *ctx)
6562 57951c27 aurel32
{
6563 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {
6564 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);
6565 57951c27 aurel32
        return;
6566 57951c27 aurel32
    }
6567 57951c27 aurel32
#if defined(TARGET_PPC64)
6568 a7812ae4 pbrook
    TCGv t0 = tcg_temp_new();
6569 a7812ae4 pbrook
    TCGv t1 = tcg_temp_new();
6570 57951c27 aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6571 57951c27 aurel32
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6572 57951c27 aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6573 57951c27 aurel32
    tcg_temp_free(t0);
6574 57951c27 aurel32
    tcg_temp_free(t1);
6575 57951c27 aurel32
#else
6576 57951c27 aurel32
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6577 57951c27 aurel32
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6578 57951c27 aurel32
#endif
6579 57951c27 aurel32
}
6580 57951c27 aurel32
static always_inline void gen_evmergehilo (DisasContext *ctx)
6581 57951c27 aurel32
{
6582 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {
6583 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);
6584 57951c27 aurel32
        return;
6585 57951c27 aurel32
    }
6586 57951c27 aurel32
#if defined(TARGET_PPC64)
6587 a7812ae4 pbrook
    TCGv t0 = tcg_temp_new();
6588 a7812ae4 pbrook
    TCGv t1 = tcg_temp_new();
6589 57951c27 aurel32
    tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6590 57951c27 aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6591 57951c27 aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6592 57951c27 aurel32
    tcg_temp_free(t0);
6593 57951c27 aurel32
    tcg_temp_free(t1);
6594 57951c27 aurel32
#else
6595 57951c27 aurel32
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6596 57951c27 aurel32
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6597 57951c27 aurel32
#endif
6598 57951c27 aurel32
}
6599 57951c27 aurel32
static always_inline void gen_evmergelohi (DisasContext *ctx)
6600 57951c27 aurel32
{
6601 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {
6602 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);
6603 57951c27 aurel32
        return;
6604 57951c27 aurel32
    }
6605 57951c27 aurel32
#if defined(TARGET_PPC64)
6606 a7812ae4 pbrook
    TCGv t0 = tcg_temp_new();
6607 a7812ae4 pbrook
    TCGv t1 = tcg_temp_new();
6608 57951c27 aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6609 57951c27 aurel32
    tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6610 57951c27 aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6611 57951c27 aurel32
    tcg_temp_free(t0);
6612 57951c27 aurel32
    tcg_temp_free(t1);
6613 57951c27 aurel32
#else
6614 57951c27 aurel32
    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6615 57951c27 aurel32
    tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6616 57951c27 aurel32
#endif
6617 57951c27 aurel32
}
6618 57951c27 aurel32
static always_inline void gen_evsplati (DisasContext *ctx)
6619 57951c27 aurel32
{
6620 38d14952 aurel32
    uint64_t imm = ((int32_t)(rA(ctx->opcode) << 11)) >> 27;
6621 0487d6a8 j_mayer
6622 57951c27 aurel32
#if defined(TARGET_PPC64)
6623 38d14952 aurel32
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
6624 57951c27 aurel32
#else
6625 57951c27 aurel32
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6626 57951c27 aurel32
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6627 57951c27 aurel32
#endif
6628 57951c27 aurel32
}
6629 b068d6a7 j_mayer
static always_inline void gen_evsplatfi (DisasContext *ctx)
6630 0487d6a8 j_mayer
{
6631 38d14952 aurel32
    uint64_t imm = rA(ctx->opcode) << 11;
6632 0487d6a8 j_mayer
6633 57951c27 aurel32
#if defined(TARGET_PPC64)
6634 38d14952 aurel32
    tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
6635 57951c27 aurel32
#else
6636 57951c27 aurel32
    tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6637 57951c27 aurel32
    tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6638 57951c27 aurel32
#endif
6639 0487d6a8 j_mayer
}
6640 0487d6a8 j_mayer
6641 57951c27 aurel32
static always_inline void gen_evsel (DisasContext *ctx)
6642 57951c27 aurel32
{
6643 57951c27 aurel32
    int l1 = gen_new_label();
6644 57951c27 aurel32
    int l2 = gen_new_label();
6645 57951c27 aurel32
    int l3 = gen_new_label();
6646 57951c27 aurel32
    int l4 = gen_new_label();
6647 a7812ae4 pbrook
    TCGv_i32 t0 = tcg_temp_local_new_i32();
6648 57951c27 aurel32
#if defined(TARGET_PPC64)
6649 a7812ae4 pbrook
    TCGv t1 = tcg_temp_local_new();
6650 a7812ae4 pbrook
    TCGv t2 = tcg_temp_local_new();
6651 57951c27 aurel32
#endif
6652 57951c27 aurel32
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
6653 57951c27 aurel32
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
6654 57951c27 aurel32
#if defined(TARGET_PPC64)
6655 57951c27 aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
6656 57951c27 aurel32
#else
6657 57951c27 aurel32
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6658 57951c27 aurel32
#endif
6659 57951c27 aurel32
    tcg_gen_br(l2);
6660 57951c27 aurel32
    gen_set_label(l1);
6661 57951c27 aurel32
#if defined(TARGET_PPC64)
6662 57951c27 aurel32
    tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
6663 57951c27 aurel32
#else
6664 57951c27 aurel32
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6665 57951c27 aurel32
#endif
6666 57951c27 aurel32
    gen_set_label(l2);
6667 57951c27 aurel32
    tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
6668 57951c27 aurel32
    tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
6669 57951c27 aurel32
#if defined(TARGET_PPC64)
6670 57951c27 aurel32
    tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
6671 57951c27 aurel32
#else
6672 57951c27 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6673 57951c27 aurel32
#endif
6674 57951c27 aurel32
    tcg_gen_br(l4);
6675 57951c27 aurel32
    gen_set_label(l3);
6676 57951c27 aurel32
#if defined(TARGET_PPC64)
6677 57951c27 aurel32
    tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
6678 57951c27 aurel32
#else
6679 57951c27 aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6680 57951c27 aurel32
#endif
6681 57951c27 aurel32
    gen_set_label(l4);
6682 a7812ae4 pbrook
    tcg_temp_free_i32(t0);
6683 57951c27 aurel32
#if defined(TARGET_PPC64)
6684 57951c27 aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
6685 57951c27 aurel32
    tcg_temp_free(t1);
6686 57951c27 aurel32
    tcg_temp_free(t2);
6687 57951c27 aurel32
#endif
6688 57951c27 aurel32
}
6689 57951c27 aurel32
GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
6690 57951c27 aurel32
{
6691 57951c27 aurel32
    gen_evsel(ctx);
6692 57951c27 aurel32
}
6693 57951c27 aurel32
GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
6694 57951c27 aurel32
{
6695 57951c27 aurel32
    gen_evsel(ctx);
6696 57951c27 aurel32
}
6697 57951c27 aurel32
GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
6698 57951c27 aurel32
{
6699 57951c27 aurel32
    gen_evsel(ctx);
6700 57951c27 aurel32
}
6701 57951c27 aurel32
GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
6702 57951c27 aurel32
{
6703 57951c27 aurel32
    gen_evsel(ctx);
6704 57951c27 aurel32
}
6705 0487d6a8 j_mayer
6706 0487d6a8 j_mayer
GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE); ////
6707 0487d6a8 j_mayer
GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE);
6708 0487d6a8 j_mayer
GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE); ////
6709 0487d6a8 j_mayer
GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE);
6710 0487d6a8 j_mayer
GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE); ////
6711 0487d6a8 j_mayer
GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE); ////
6712 0487d6a8 j_mayer
GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE); ////
6713 0487d6a8 j_mayer
GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE); //
6714 0487d6a8 j_mayer
GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE); ////
6715 0487d6a8 j_mayer
GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE); ////
6716 0487d6a8 j_mayer
GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE); ////
6717 0487d6a8 j_mayer
GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE); ////
6718 0487d6a8 j_mayer
GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE); ////
6719 0487d6a8 j_mayer
GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE); ////
6720 0487d6a8 j_mayer
GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE); ////
6721 0487d6a8 j_mayer
GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE);
6722 0487d6a8 j_mayer
GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE); ////
6723 0487d6a8 j_mayer
GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE);
6724 0487d6a8 j_mayer
GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE); //
6725 0487d6a8 j_mayer
GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE);
6726 0487d6a8 j_mayer
GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE); ////
6727 0487d6a8 j_mayer
GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE); ////
6728 0487d6a8 j_mayer
GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE); ////
6729 0487d6a8 j_mayer
GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE); ////
6730 0487d6a8 j_mayer
GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE); ////
6731 0487d6a8 j_mayer
6732 6a6ae23f aurel32
/* SPE load and stores */
6733 76db3ba4 aurel32
static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, TCGv EA, int sh)
6734 6a6ae23f aurel32
{
6735 6a6ae23f aurel32
    target_ulong uimm = rB(ctx->opcode);
6736 6a6ae23f aurel32
6737 76db3ba4 aurel32
    if (rA(ctx->opcode) == 0) {
6738 6a6ae23f aurel32
        tcg_gen_movi_tl(EA, uimm << sh);
6739 76db3ba4 aurel32
    } else {
6740 6a6ae23f aurel32
        tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
6741 76db3ba4 aurel32
#if defined(TARGET_PPC64)
6742 76db3ba4 aurel32
        if (!ctx->sf_mode) {
6743 76db3ba4 aurel32
            tcg_gen_ext32u_tl(EA, EA);
6744 76db3ba4 aurel32
        }
6745 76db3ba4 aurel32
#endif
6746 76db3ba4 aurel32
    }
6747 0487d6a8 j_mayer
}
6748 6a6ae23f aurel32
6749 6a6ae23f aurel32
static always_inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
6750 6a6ae23f aurel32
{
6751 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6752 76db3ba4 aurel32
    gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6753 6a6ae23f aurel32
#else
6754 6a6ae23f aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();
6755 76db3ba4 aurel32
    gen_qemu_ld64(ctx, t0, addr);
6756 6a6ae23f aurel32
    tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
6757 6a6ae23f aurel32
    tcg_gen_shri_i64(t0, t0, 32);
6758 6a6ae23f aurel32
    tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
6759 6a6ae23f aurel32
    tcg_temp_free_i64(t0);
6760 6a6ae23f aurel32
#endif
6761 0487d6a8 j_mayer
}
6762 6a6ae23f aurel32
6763 6a6ae23f aurel32
static always_inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
6764 6a6ae23f aurel32
{
6765 0487d6a8 j_mayer
#if defined(TARGET_PPC64)
6766 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6767 76db3ba4 aurel32
    gen_qemu_ld32u(ctx, t0, addr);
6768 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6769 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 4);
6770 76db3ba4 aurel32
    gen_qemu_ld32u(ctx, t0, addr);
6771 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6772 6a6ae23f aurel32
    tcg_temp_free(t0);
6773 6a6ae23f aurel32
#else
6774 76db3ba4 aurel32
    gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
6775 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 4);
6776 76db3ba4 aurel32
    gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6777 6a6ae23f aurel32
#endif
6778 0487d6a8 j_mayer
}
6779 6a6ae23f aurel32
6780 6a6ae23f aurel32
static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
6781 6a6ae23f aurel32
{
6782 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6783 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6784 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6785 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6786 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6787 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6788 6a6ae23f aurel32
    tcg_gen_shli_tl(t0, t0, 32);
6789 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6790 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6791 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6792 6a6ae23f aurel32
    tcg_gen_shli_tl(t0, t0, 16);
6793 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6794 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6795 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6796 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6797 0487d6a8 j_mayer
#else
6798 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6799 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6800 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6801 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6802 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6803 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6804 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6805 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6806 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6807 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6808 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6809 0487d6a8 j_mayer
#endif
6810 6a6ae23f aurel32
    tcg_temp_free(t0);
6811 0487d6a8 j_mayer
}
6812 0487d6a8 j_mayer
6813 6a6ae23f aurel32
static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
6814 6a6ae23f aurel32
{
6815 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6816 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6817 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6818 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6819 6a6ae23f aurel32
    tcg_gen_shli_tl(t0, t0, 16);
6820 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6821 6a6ae23f aurel32
#else
6822 6a6ae23f aurel32
    tcg_gen_shli_tl(t0, t0, 16);
6823 6a6ae23f aurel32
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6824 6a6ae23f aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6825 6a6ae23f aurel32
#endif
6826 6a6ae23f aurel32
    tcg_temp_free(t0);
6827 0487d6a8 j_mayer
}
6828 0487d6a8 j_mayer
6829 6a6ae23f aurel32
static always_inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
6830 6a6ae23f aurel32
{
6831 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6832 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6833 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6834 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6835 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6836 6a6ae23f aurel32
#else
6837 6a6ae23f aurel32
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6838 6a6ae23f aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6839 6a6ae23f aurel32
#endif
6840 6a6ae23f aurel32
    tcg_temp_free(t0);
6841 0487d6a8 j_mayer
}
6842 0487d6a8 j_mayer
6843 6a6ae23f aurel32
static always_inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
6844 6a6ae23f aurel32
{
6845 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6846 76db3ba4 aurel32
    gen_qemu_ld16s(ctx, t0, addr);
6847 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6848 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6849 6a6ae23f aurel32
    tcg_gen_ext32u_tl(t0, t0);
6850 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6851 6a6ae23f aurel32
#else
6852 6a6ae23f aurel32
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6853 6a6ae23f aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6854 6a6ae23f aurel32
#endif
6855 6a6ae23f aurel32
    tcg_temp_free(t0);
6856 6a6ae23f aurel32
}
6857 6a6ae23f aurel32
6858 6a6ae23f aurel32
static always_inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
6859 6a6ae23f aurel32
{
6860 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6861 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6862 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6863 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6864 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6865 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6866 6a6ae23f aurel32
    tcg_gen_shli_tl(t0, t0, 16);
6867 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6868 6a6ae23f aurel32
#else
6869 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6870 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6871 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6872 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6873 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
6874 6a6ae23f aurel32
#endif
6875 6a6ae23f aurel32
    tcg_temp_free(t0);
6876 6a6ae23f aurel32
}
6877 6a6ae23f aurel32
6878 6a6ae23f aurel32
static always_inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
6879 6a6ae23f aurel32
{
6880 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6881 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6882 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6883 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6884 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6885 6a6ae23f aurel32
    tcg_gen_shli_tl(t0, t0, 32);
6886 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6887 6a6ae23f aurel32
    tcg_temp_free(t0);
6888 6a6ae23f aurel32
#else
6889 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
6890 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6891 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6892 6a6ae23f aurel32
#endif
6893 6a6ae23f aurel32
}
6894 6a6ae23f aurel32
6895 6a6ae23f aurel32
static always_inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
6896 6a6ae23f aurel32
{
6897 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6898 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6899 76db3ba4 aurel32
    gen_qemu_ld16s(ctx, t0, addr);
6900 6a6ae23f aurel32
    tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
6901 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6902 76db3ba4 aurel32
    gen_qemu_ld16s(ctx, t0, addr);
6903 6a6ae23f aurel32
    tcg_gen_shli_tl(t0, t0, 32);
6904 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6905 6a6ae23f aurel32
    tcg_temp_free(t0);
6906 6a6ae23f aurel32
#else
6907 76db3ba4 aurel32
    gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
6908 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6909 76db3ba4 aurel32
    gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6910 6a6ae23f aurel32
#endif
6911 6a6ae23f aurel32
}
6912 6a6ae23f aurel32
6913 6a6ae23f aurel32
static always_inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
6914 6a6ae23f aurel32
{
6915 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6916 76db3ba4 aurel32
    gen_qemu_ld32u(ctx, t0, addr);
6917 0487d6a8 j_mayer
#if defined(TARGET_PPC64)
6918 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6919 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6920 6a6ae23f aurel32
#else
6921 6a6ae23f aurel32
    tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6922 6a6ae23f aurel32
    tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6923 6a6ae23f aurel32
#endif
6924 6a6ae23f aurel32
    tcg_temp_free(t0);
6925 6a6ae23f aurel32
}
6926 6a6ae23f aurel32
6927 6a6ae23f aurel32
static always_inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
6928 6a6ae23f aurel32
{
6929 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6930 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6931 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6932 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6933 6a6ae23f aurel32
    tcg_gen_shli_tl(t0, t0, 32);
6934 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6935 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6936 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6937 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6938 6a6ae23f aurel32
    tcg_gen_shli_tl(t0, t0, 16);
6939 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6940 6a6ae23f aurel32
#else
6941 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6942 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6943 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6944 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6945 76db3ba4 aurel32
    gen_qemu_ld16u(ctx, t0, addr);
6946 6a6ae23f aurel32
    tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
6947 6a6ae23f aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6948 0487d6a8 j_mayer
#endif
6949 6a6ae23f aurel32
    tcg_temp_free(t0);
6950 6a6ae23f aurel32
}
6951 6a6ae23f aurel32
6952 6a6ae23f aurel32
static always_inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
6953 6a6ae23f aurel32
{
6954 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6955 76db3ba4 aurel32
    gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6956 0487d6a8 j_mayer
#else
6957 6a6ae23f aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();
6958 6a6ae23f aurel32
    tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
6959 76db3ba4 aurel32
    gen_qemu_st64(ctx, t0, addr);
6960 6a6ae23f aurel32
    tcg_temp_free_i64(t0);
6961 6a6ae23f aurel32
#endif
6962 6a6ae23f aurel32
}
6963 6a6ae23f aurel32
6964 6a6ae23f aurel32
static always_inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
6965 6a6ae23f aurel32
{
6966 0487d6a8 j_mayer
#if defined(TARGET_PPC64)
6967 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6968 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6969 76db3ba4 aurel32
    gen_qemu_st32(ctx, t0, addr);
6970 6a6ae23f aurel32
    tcg_temp_free(t0);
6971 6a6ae23f aurel32
#else
6972 76db3ba4 aurel32
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6973 6a6ae23f aurel32
#endif
6974 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 4);
6975 76db3ba4 aurel32
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6976 6a6ae23f aurel32
}
6977 6a6ae23f aurel32
6978 6a6ae23f aurel32
static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
6979 6a6ae23f aurel32
{
6980 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
6981 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6982 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
6983 6a6ae23f aurel32
#else
6984 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
6985 6a6ae23f aurel32
#endif
6986 76db3ba4 aurel32
    gen_qemu_st16(ctx, t0, addr);
6987 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6988 6a6ae23f aurel32
#if defined(TARGET_PPC64)
6989 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6990 76db3ba4 aurel32
    gen_qemu_st16(ctx, t0, addr);
6991 6a6ae23f aurel32
#else
6992 76db3ba4 aurel32
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6993 6a6ae23f aurel32
#endif
6994 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6995 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
6996 76db3ba4 aurel32
    gen_qemu_st16(ctx, t0, addr);
6997 6a6ae23f aurel32
    tcg_temp_free(t0);
6998 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
6999 76db3ba4 aurel32
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7000 6a6ae23f aurel32
}
7001 6a6ae23f aurel32
7002 6a6ae23f aurel32
static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
7003 6a6ae23f aurel32
{
7004 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
7005 6a6ae23f aurel32
#if defined(TARGET_PPC64)
7006 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7007 6a6ae23f aurel32
#else
7008 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7009 6a6ae23f aurel32
#endif
7010 76db3ba4 aurel32
    gen_qemu_st16(ctx, t0, addr);
7011 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
7012 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7013 76db3ba4 aurel32
    gen_qemu_st16(ctx, t0, addr);
7014 6a6ae23f aurel32
    tcg_temp_free(t0);
7015 6a6ae23f aurel32
}
7016 6a6ae23f aurel32
7017 6a6ae23f aurel32
static always_inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7018 6a6ae23f aurel32
{
7019 6a6ae23f aurel32
#if defined(TARGET_PPC64)
7020 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
7021 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7022 76db3ba4 aurel32
    gen_qemu_st16(ctx, t0, addr);
7023 6a6ae23f aurel32
    tcg_temp_free(t0);
7024 6a6ae23f aurel32
#else
7025 76db3ba4 aurel32
    gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7026 6a6ae23f aurel32
#endif
7027 76db3ba4 aurel32
    gen_addr_add(ctx, addr, addr, 2);
7028 76db3ba4 aurel32
    gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7029 6a6ae23f aurel32
}
7030 6a6ae23f aurel32
7031 6a6ae23f aurel32
static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7032 6a6ae23f aurel32
{
7033 6a6ae23f aurel32
#if defined(TARGET_PPC64)
7034 6a6ae23f aurel32
    TCGv t0 = tcg_temp_new();
7035 6a6ae23f aurel32
    tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7036 76db3ba4 aurel32
    gen_qemu_st32(ctx, t0, addr);
7037 6a6ae23f aurel32
    tcg_temp_free(t0);
7038 6a6ae23f aurel32
#else
7039 76db3ba4 aurel32
    gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
7040 6a6ae23f aurel32
#endif
7041 6a6ae23f aurel32
}
7042 6a6ae23f aurel32
7043 6a6ae23f aurel32
static always_inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7044 6a6ae23f aurel32
{
7045 76db3ba4 aurel32
    gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
7046 6a6ae23f aurel32
}
7047 6a6ae23f aurel32
7048 6a6ae23f aurel32
#define GEN_SPEOP_LDST(name, opc2, sh)                                        \
7049 76db3ba4 aurel32
GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)                      \
7050 6a6ae23f aurel32
{                                                                             \
7051 6a6ae23f aurel32
    TCGv t0;                                                                  \
7052 6a6ae23f aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7053 6a6ae23f aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
7054 6a6ae23f aurel32
        return;                                                               \
7055 6a6ae23f aurel32
    }                                                                         \
7056 76db3ba4 aurel32
    gen_set_access_type(ctx, ACCESS_INT);                                     \
7057 6a6ae23f aurel32
    t0 = tcg_temp_new();                                                      \
7058 6a6ae23f aurel32
    if (Rc(ctx->opcode)) {                                                    \
7059 76db3ba4 aurel32
        gen_addr_spe_imm_index(ctx, t0, sh);                                  \
7060 6a6ae23f aurel32
    } else {                                                                  \
7061 76db3ba4 aurel32
        gen_addr_reg_index(ctx, t0);                                          \
7062 6a6ae23f aurel32
    }                                                                         \
7063 6a6ae23f aurel32
    gen_op_##name(ctx, t0);                                                   \
7064 6a6ae23f aurel32
    tcg_temp_free(t0);                                                        \
7065 6a6ae23f aurel32
}
7066 6a6ae23f aurel32
7067 6a6ae23f aurel32
GEN_SPEOP_LDST(evldd, 0x00, 3);
7068 6a6ae23f aurel32
GEN_SPEOP_LDST(evldw, 0x01, 3);
7069 6a6ae23f aurel32
GEN_SPEOP_LDST(evldh, 0x02, 3);
7070 6a6ae23f aurel32
GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
7071 6a6ae23f aurel32
GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
7072 6a6ae23f aurel32
GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
7073 6a6ae23f aurel32
GEN_SPEOP_LDST(evlwhe, 0x08, 2);
7074 6a6ae23f aurel32
GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
7075 6a6ae23f aurel32
GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
7076 6a6ae23f aurel32
GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
7077 6a6ae23f aurel32
GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
7078 6a6ae23f aurel32
7079 6a6ae23f aurel32
GEN_SPEOP_LDST(evstdd, 0x10, 3);
7080 6a6ae23f aurel32
GEN_SPEOP_LDST(evstdw, 0x11, 3);
7081 6a6ae23f aurel32
GEN_SPEOP_LDST(evstdh, 0x12, 3);
7082 6a6ae23f aurel32
GEN_SPEOP_LDST(evstwhe, 0x18, 2);
7083 6a6ae23f aurel32
GEN_SPEOP_LDST(evstwho, 0x1A, 2);
7084 6a6ae23f aurel32
GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
7085 6a6ae23f aurel32
GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
7086 0487d6a8 j_mayer
7087 0487d6a8 j_mayer
/* Multiply and add - TODO */
7088 0487d6a8 j_mayer
#if 0
7089 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0x00000000, PPC_SPE);
7090 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0x00000000, PPC_SPE);
7091 0487d6a8 j_mayer
GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, PPC_SPE);
7092 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0x00000000, PPC_SPE);
7093 0487d6a8 j_mayer
GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, PPC_SPE);
7094 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0x00000000, PPC_SPE);
7095 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0x00000000, PPC_SPE);
7096 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0x00000000, PPC_SPE);
7097 0487d6a8 j_mayer
GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, PPC_SPE);
7098 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0x00000000, PPC_SPE);
7099 0487d6a8 j_mayer
GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, PPC_SPE);
7100 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0x00000000, PPC_SPE);
7101 0487d6a8 j_mayer

7102 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
7103 0487d6a8 j_mayer
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
7104 0487d6a8 j_mayer
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
7105 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
7106 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
7107 0487d6a8 j_mayer
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
7108 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
7109 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
7110 0487d6a8 j_mayer
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
7111 0487d6a8 j_mayer
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
7112 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
7113 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
7114 0487d6a8 j_mayer
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
7115 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
7116 0487d6a8 j_mayer

7117 0487d6a8 j_mayer
GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
7118 0487d6a8 j_mayer
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
7119 0487d6a8 j_mayer
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
7120 0487d6a8 j_mayer
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
7121 0487d6a8 j_mayer
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
7122 0487d6a8 j_mayer
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
7123 0487d6a8 j_mayer

7124 0487d6a8 j_mayer
GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
7125 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
7126 0487d6a8 j_mayer
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
7127 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
7128 0487d6a8 j_mayer
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
7129 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
7130 0487d6a8 j_mayer
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
7131 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
7132 0487d6a8 j_mayer
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
7133 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
7134 0487d6a8 j_mayer
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
7135 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
7136 0487d6a8 j_mayer

7137 0487d6a8 j_mayer
GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
7138 0487d6a8 j_mayer
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
7139 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
7140 0487d6a8 j_mayer
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
7141 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
7142 0487d6a8 j_mayer

7143 0487d6a8 j_mayer
GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
7144 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
7145 0487d6a8 j_mayer
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
7146 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
7147 0487d6a8 j_mayer
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
7148 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
7149 0487d6a8 j_mayer
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
7150 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
7151 0487d6a8 j_mayer
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
7152 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
7153 0487d6a8 j_mayer
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
7154 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
7155 0487d6a8 j_mayer

7156 0487d6a8 j_mayer
GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, PPC_SPE);
7157 0487d6a8 j_mayer
GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, PPC_SPE);
7158 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0x00000000, PPC_SPE);
7159 0487d6a8 j_mayer
GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, PPC_SPE);
7160 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0x00000000, PPC_SPE);
7161 0487d6a8 j_mayer
#endif
7162 0487d6a8 j_mayer
7163 0487d6a8 j_mayer
/***                      SPE floating-point extension                     ***/
7164 1c97856d aurel32
#if defined(TARGET_PPC64)
7165 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
7166 b068d6a7 j_mayer
static always_inline void gen_##name (DisasContext *ctx)                      \
7167 0487d6a8 j_mayer
{                                                                             \
7168 1c97856d aurel32
    TCGv_i32 t0;                                                              \
7169 1c97856d aurel32
    TCGv t1;                                                                  \
7170 1c97856d aurel32
    t0 = tcg_temp_new_i32();                                                  \
7171 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
7172 1c97856d aurel32
    gen_helper_##name(t0, t0);                                                \
7173 1c97856d aurel32
    t1 = tcg_temp_new();                                                      \
7174 1c97856d aurel32
    tcg_gen_extu_i32_tl(t1, t0);                                              \
7175 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7176 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7177 1c97856d aurel32
                    0xFFFFFFFF00000000ULL);                                   \
7178 1c97856d aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
7179 1c97856d aurel32
    tcg_temp_free(t1);                                                        \
7180 0487d6a8 j_mayer
}
7181 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
7182 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7183 1c97856d aurel32
{                                                                             \
7184 1c97856d aurel32
    TCGv_i32 t0;                                                              \
7185 1c97856d aurel32
    TCGv t1;                                                                  \
7186 1c97856d aurel32
    t0 = tcg_temp_new_i32();                                                  \
7187 1c97856d aurel32
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
7188 1c97856d aurel32
    t1 = tcg_temp_new();                                                      \
7189 1c97856d aurel32
    tcg_gen_extu_i32_tl(t1, t0);                                              \
7190 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7191 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7192 1c97856d aurel32
                    0xFFFFFFFF00000000ULL);                                   \
7193 1c97856d aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
7194 1c97856d aurel32
    tcg_temp_free(t1);                                                        \
7195 1c97856d aurel32
}
7196 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
7197 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7198 1c97856d aurel32
{                                                                             \
7199 1c97856d aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
7200 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
7201 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
7202 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7203 1c97856d aurel32
}
7204 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
7205 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7206 1c97856d aurel32
{                                                                             \
7207 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7208 1c97856d aurel32
}
7209 1c97856d aurel32
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
7210 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7211 57951c27 aurel32
{                                                                             \
7212 1c97856d aurel32
    TCGv_i32 t0, t1;                                                          \
7213 1c97856d aurel32
    TCGv_i64 t2;                                                              \
7214 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7215 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
7216 57951c27 aurel32
        return;                                                               \
7217 57951c27 aurel32
    }                                                                         \
7218 1c97856d aurel32
    t0 = tcg_temp_new_i32();                                                  \
7219 1c97856d aurel32
    t1 = tcg_temp_new_i32();                                                  \
7220 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
7221 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
7222 1c97856d aurel32
    gen_helper_##name(t0, t0, t1);                                            \
7223 1c97856d aurel32
    tcg_temp_free_i32(t1);                                                    \
7224 1c97856d aurel32
    t2 = tcg_temp_new();                                                      \
7225 1c97856d aurel32
    tcg_gen_extu_i32_tl(t2, t0);                                              \
7226 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7227 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7228 1c97856d aurel32
                    0xFFFFFFFF00000000ULL);                                   \
7229 1c97856d aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2);    \
7230 1c97856d aurel32
    tcg_temp_free(t2);                                                        \
7231 57951c27 aurel32
}
7232 1c97856d aurel32
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
7233 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7234 57951c27 aurel32
{                                                                             \
7235 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7236 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
7237 57951c27 aurel32
        return;                                                               \
7238 57951c27 aurel32
    }                                                                         \
7239 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],     \
7240 1c97856d aurel32
                      cpu_gpr[rB(ctx->opcode)]);                              \
7241 57951c27 aurel32
}
7242 1c97856d aurel32
#define GEN_SPEFPUOP_COMP_32(name)                                            \
7243 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7244 57951c27 aurel32
{                                                                             \
7245 1c97856d aurel32
    TCGv_i32 t0, t1;                                                          \
7246 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7247 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
7248 57951c27 aurel32
        return;                                                               \
7249 57951c27 aurel32
    }                                                                         \
7250 1c97856d aurel32
    t0 = tcg_temp_new_i32();                                                  \
7251 1c97856d aurel32
    t1 = tcg_temp_new_i32();                                                  \
7252 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
7253 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
7254 1c97856d aurel32
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
7255 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7256 1c97856d aurel32
    tcg_temp_free_i32(t1);                                                    \
7257 1c97856d aurel32
}
7258 1c97856d aurel32
#define GEN_SPEFPUOP_COMP_64(name)                                            \
7259 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7260 1c97856d aurel32
{                                                                             \
7261 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7262 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
7263 1c97856d aurel32
        return;                                                               \
7264 1c97856d aurel32
    }                                                                         \
7265 1c97856d aurel32
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
7266 1c97856d aurel32
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7267 1c97856d aurel32
}
7268 1c97856d aurel32
#else
7269 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
7270 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7271 1c97856d aurel32
{                                                                             \
7272 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7273 57951c27 aurel32
}
7274 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
7275 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7276 1c97856d aurel32
{                                                                             \
7277 1c97856d aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7278 1c97856d aurel32
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
7279 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
7280 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7281 1c97856d aurel32
}
7282 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
7283 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7284 1c97856d aurel32
{                                                                             \
7285 1c97856d aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7286 1c97856d aurel32
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
7287 1c97856d aurel32
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7288 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7289 1c97856d aurel32
}
7290 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
7291 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7292 1c97856d aurel32
{                                                                             \
7293 1c97856d aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7294 1c97856d aurel32
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
7295 1c97856d aurel32
    gen_helper_##name(t0, t0);                                                \
7296 1c97856d aurel32
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7297 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7298 1c97856d aurel32
}
7299 1c97856d aurel32
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
7300 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7301 1c97856d aurel32
{                                                                             \
7302 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7303 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
7304 1c97856d aurel32
        return;                                                               \
7305 1c97856d aurel32
    }                                                                         \
7306 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)],                               \
7307 1c97856d aurel32
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7308 1c97856d aurel32
}
7309 1c97856d aurel32
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
7310 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7311 1c97856d aurel32
{                                                                             \
7312 1c97856d aurel32
    TCGv_i64 t0, t1;                                                          \
7313 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7314 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
7315 1c97856d aurel32
        return;                                                               \
7316 1c97856d aurel32
    }                                                                         \
7317 1c97856d aurel32
    t0 = tcg_temp_new_i64();                                                  \
7318 1c97856d aurel32
    t1 = tcg_temp_new_i64();                                                  \
7319 1c97856d aurel32
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
7320 1c97856d aurel32
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
7321 1c97856d aurel32
    gen_helper_##name(t0, t0, t1);                                            \
7322 1c97856d aurel32
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7323 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7324 1c97856d aurel32
    tcg_temp_free_i64(t1);                                                    \
7325 1c97856d aurel32
}
7326 1c97856d aurel32
#define GEN_SPEFPUOP_COMP_32(name)                                            \
7327 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7328 1c97856d aurel32
{                                                                             \
7329 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7330 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
7331 1c97856d aurel32
        return;                                                               \
7332 1c97856d aurel32
    }                                                                         \
7333 1c97856d aurel32
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
7334 1c97856d aurel32
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7335 1c97856d aurel32
}
7336 1c97856d aurel32
#define GEN_SPEFPUOP_COMP_64(name)                                            \
7337 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7338 1c97856d aurel32
{                                                                             \
7339 1c97856d aurel32
    TCGv_i64 t0, t1;                                                          \
7340 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7341 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
7342 1c97856d aurel32
        return;                                                               \
7343 1c97856d aurel32
    }                                                                         \
7344 1c97856d aurel32
    t0 = tcg_temp_new_i64();                                                  \
7345 1c97856d aurel32
    t1 = tcg_temp_new_i64();                                                  \
7346 1c97856d aurel32
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
7347 1c97856d aurel32
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
7348 1c97856d aurel32
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
7349 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7350 1c97856d aurel32
    tcg_temp_free_i64(t1);                                                    \
7351 1c97856d aurel32
}
7352 1c97856d aurel32
#endif
7353 57951c27 aurel32
7354 0487d6a8 j_mayer
/* Single precision floating-point vectors operations */
7355 0487d6a8 j_mayer
/* Arithmetic */
7356 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
7357 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(evfssub);
7358 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
7359 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
7360 1c97856d aurel32
static always_inline void gen_evfsabs (DisasContext *ctx)
7361 1c97856d aurel32
{
7362 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7363 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);
7364 1c97856d aurel32
        return;
7365 1c97856d aurel32
    }
7366 1c97856d aurel32
#if defined(TARGET_PPC64)
7367 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
7368 1c97856d aurel32
#else
7369 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
7370 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7371 1c97856d aurel32
#endif
7372 1c97856d aurel32
}
7373 1c97856d aurel32
static always_inline void gen_evfsnabs (DisasContext *ctx)
7374 1c97856d aurel32
{
7375 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7376 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);
7377 1c97856d aurel32
        return;
7378 1c97856d aurel32
    }
7379 1c97856d aurel32
#if defined(TARGET_PPC64)
7380 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7381 1c97856d aurel32
#else
7382 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7383 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7384 1c97856d aurel32
#endif
7385 1c97856d aurel32
}
7386 1c97856d aurel32
static always_inline void gen_evfsneg (DisasContext *ctx)
7387 1c97856d aurel32
{
7388 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7389 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);
7390 1c97856d aurel32
        return;
7391 1c97856d aurel32
    }
7392 1c97856d aurel32
#if defined(TARGET_PPC64)
7393 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7394 1c97856d aurel32
#else
7395 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7396 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7397 1c97856d aurel32
#endif
7398 1c97856d aurel32
}
7399 1c97856d aurel32
7400 0487d6a8 j_mayer
/* Conversion */
7401 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfscfui);
7402 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfscfsi);
7403 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfscfuf);
7404 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfscfsf);
7405 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctui);
7406 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctsi);
7407 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctuf);
7408 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctsf);
7409 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
7410 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
7411 1c97856d aurel32
7412 0487d6a8 j_mayer
/* Comparison */
7413 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfscmpgt);
7414 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfscmplt);
7415 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfscmpeq);
7416 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfststgt);
7417 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfststlt);
7418 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfststeq);
7419 0487d6a8 j_mayer
7420 0487d6a8 j_mayer
/* Opcodes definitions */
7421 0487d6a8 j_mayer
GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
7422 0487d6a8 j_mayer
GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
7423 0487d6a8 j_mayer
GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
7424 0487d6a8 j_mayer
GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
7425 0487d6a8 j_mayer
GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
7426 0487d6a8 j_mayer
GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
7427 0487d6a8 j_mayer
GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
7428 0487d6a8 j_mayer
GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
7429 0487d6a8 j_mayer
GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
7430 0487d6a8 j_mayer
GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
7431 0487d6a8 j_mayer
GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
7432 0487d6a8 j_mayer
GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
7433 0487d6a8 j_mayer
GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
7434 0487d6a8 j_mayer
GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
7435 0487d6a8 j_mayer
7436 0487d6a8 j_mayer
/* Single precision floating-point operations */
7437 0487d6a8 j_mayer
/* Arithmetic */
7438 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_32_32(efsadd);
7439 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_32_32(efssub);
7440 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_32_32(efsmul);
7441 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
7442 1c97856d aurel32
static always_inline void gen_efsabs (DisasContext *ctx)
7443 1c97856d aurel32
{
7444 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7445 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);
7446 1c97856d aurel32
        return;
7447 1c97856d aurel32
    }
7448 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
7449 1c97856d aurel32
}
7450 1c97856d aurel32
static always_inline void gen_efsnabs (DisasContext *ctx)
7451 1c97856d aurel32
{
7452 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7453 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);
7454 1c97856d aurel32
        return;
7455 1c97856d aurel32
    }
7456 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7457 1c97856d aurel32
}
7458 1c97856d aurel32
static always_inline void gen_efsneg (DisasContext *ctx)
7459 1c97856d aurel32
{
7460 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7461 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);
7462 1c97856d aurel32
        return;
7463 1c97856d aurel32
    }
7464 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7465 1c97856d aurel32
}
7466 1c97856d aurel32
7467 0487d6a8 j_mayer
/* Conversion */
7468 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efscfui);
7469 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efscfsi);
7470 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efscfuf);
7471 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efscfsf);
7472 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctui);
7473 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctsi);
7474 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctuf);
7475 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctsf);
7476 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctuiz);
7477 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctsiz);
7478 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efscfd);
7479 1c97856d aurel32
7480 0487d6a8 j_mayer
/* Comparison */
7481 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efscmpgt);
7482 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efscmplt);
7483 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efscmpeq);
7484 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efststgt);
7485 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efststlt);
7486 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efststeq);
7487 0487d6a8 j_mayer
7488 0487d6a8 j_mayer
/* Opcodes definitions */
7489 05332d70 j_mayer
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
7490 0487d6a8 j_mayer
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
7491 0487d6a8 j_mayer
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
7492 0487d6a8 j_mayer
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
7493 0487d6a8 j_mayer
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
7494 0487d6a8 j_mayer
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
7495 0487d6a8 j_mayer
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
7496 0487d6a8 j_mayer
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
7497 0487d6a8 j_mayer
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
7498 0487d6a8 j_mayer
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
7499 9ceb2a77 ths
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
7500 9ceb2a77 ths
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
7501 0487d6a8 j_mayer
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
7502 0487d6a8 j_mayer
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
7503 0487d6a8 j_mayer
7504 0487d6a8 j_mayer
/* Double precision floating-point operations */
7505 0487d6a8 j_mayer
/* Arithmetic */
7506 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(efdadd);
7507 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(efdsub);
7508 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(efdmul);
7509 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(efddiv);
7510 1c97856d aurel32
static always_inline void gen_efdabs (DisasContext *ctx)
7511 1c97856d aurel32
{
7512 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7513 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);
7514 1c97856d aurel32
        return;
7515 1c97856d aurel32
    }
7516 1c97856d aurel32
#if defined(TARGET_PPC64)
7517 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
7518 1c97856d aurel32
#else
7519 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7520 1c97856d aurel32
#endif
7521 1c97856d aurel32
}
7522 1c97856d aurel32
static always_inline void gen_efdnabs (DisasContext *ctx)
7523 1c97856d aurel32
{
7524 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7525 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);
7526 1c97856d aurel32
        return;
7527 1c97856d aurel32
    }
7528 1c97856d aurel32
#if defined(TARGET_PPC64)
7529 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7530 1c97856d aurel32
#else
7531 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7532 1c97856d aurel32
#endif
7533 1c97856d aurel32
}
7534 1c97856d aurel32
static always_inline void gen_efdneg (DisasContext *ctx)
7535 1c97856d aurel32
{
7536 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7537 1c97856d aurel32
        GEN_EXCP_NO_AP(ctx);
7538 1c97856d aurel32
        return;
7539 1c97856d aurel32
    }
7540 1c97856d aurel32
#if defined(TARGET_PPC64)
7541 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7542 1c97856d aurel32
#else
7543 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7544 1c97856d aurel32
#endif
7545 1c97856d aurel32
}
7546 1c97856d aurel32
7547 0487d6a8 j_mayer
/* Conversion */
7548 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfui);
7549 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfsi);
7550 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfuf);
7551 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfsf);
7552 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctui);
7553 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctsi);
7554 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctuf);
7555 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctsf);
7556 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctuiz);
7557 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctsiz);
7558 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfs);
7559 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(efdcfuid);
7560 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(efdcfsid);
7561 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(efdctuidz);
7562 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(efdctsidz);
7563 0487d6a8 j_mayer
7564 0487d6a8 j_mayer
/* Comparison */
7565 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdcmpgt);
7566 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdcmplt);
7567 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdcmpeq);
7568 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdtstgt);
7569 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdtstlt);
7570 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdtsteq);
7571 0487d6a8 j_mayer
7572 0487d6a8 j_mayer
/* Opcodes definitions */
7573 0487d6a8 j_mayer
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
7574 0487d6a8 j_mayer
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
7575 0487d6a8 j_mayer
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
7576 0487d6a8 j_mayer
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
7577 0487d6a8 j_mayer
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
7578 0487d6a8 j_mayer
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
7579 0487d6a8 j_mayer
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
7580 0487d6a8 j_mayer
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
7581 0487d6a8 j_mayer
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
7582 0487d6a8 j_mayer
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
7583 0487d6a8 j_mayer
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
7584 0487d6a8 j_mayer
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
7585 0487d6a8 j_mayer
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
7586 0487d6a8 j_mayer
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
7587 0487d6a8 j_mayer
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
7588 0487d6a8 j_mayer
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
7589 0487d6a8 j_mayer
7590 79aceca5 bellard
/* End opcode list */
7591 79aceca5 bellard
GEN_OPCODE_MARK(end);
7592 79aceca5 bellard
7593 3fc6c082 bellard
#include "translate_init.c"
7594 0411a972 j_mayer
#include "helper_regs.h"
7595 79aceca5 bellard
7596 9a64fbe4 bellard
/*****************************************************************************/
7597 3fc6c082 bellard
/* Misc PowerPC helpers */
7598 36081602 j_mayer
void cpu_dump_state (CPUState *env, FILE *f,
7599 36081602 j_mayer
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7600 36081602 j_mayer
                     int flags)
7601 79aceca5 bellard
{
7602 3fc6c082 bellard
#define RGPL  4
7603 3fc6c082 bellard
#define RFPL  4
7604 3fc6c082 bellard
7605 79aceca5 bellard
    int i;
7606 79aceca5 bellard
7607 077fc206 j_mayer
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
7608 3d7b417e aurel32
                env->nip, env->lr, env->ctr, env->xer);
7609 6b542af7 j_mayer
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
7610 6b542af7 j_mayer
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
7611 d9bce9d9 j_mayer
#if !defined(NO_TIMER_DUMP)
7612 077fc206 j_mayer
    cpu_fprintf(f, "TB %08x %08x "
7613 76a66253 j_mayer
#if !defined(CONFIG_USER_ONLY)
7614 76a66253 j_mayer
                "DECR %08x"
7615 76a66253 j_mayer
#endif
7616 76a66253 j_mayer
                "\n",
7617 077fc206 j_mayer
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
7618 76a66253 j_mayer
#if !defined(CONFIG_USER_ONLY)
7619 76a66253 j_mayer
                , cpu_ppc_load_decr(env)
7620 76a66253 j_mayer
#endif
7621 76a66253 j_mayer
                );
7622 077fc206 j_mayer
#endif
7623 76a66253 j_mayer
    for (i = 0; i < 32; i++) {
7624 3fc6c082 bellard
        if ((i & (RGPL - 1)) == 0)
7625 3fc6c082 bellard
            cpu_fprintf(f, "GPR%02d", i);
7626 6b542af7 j_mayer
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
7627 3fc6c082 bellard
        if ((i & (RGPL - 1)) == (RGPL - 1))
7628 7fe48483 bellard
            cpu_fprintf(f, "\n");
7629 76a66253 j_mayer
    }
7630 3fc6c082 bellard
    cpu_fprintf(f, "CR ");
7631 76a66253 j_mayer
    for (i = 0; i < 8; i++)
7632 7fe48483 bellard
        cpu_fprintf(f, "%01x", env->crf[i]);
7633 7fe48483 bellard
    cpu_fprintf(f, "  [");
7634 76a66253 j_mayer
    for (i = 0; i < 8; i++) {
7635 76a66253 j_mayer
        char a = '-';
7636 76a66253 j_mayer
        if (env->crf[i] & 0x08)
7637 76a66253 j_mayer
            a = 'L';
7638 76a66253 j_mayer
        else if (env->crf[i] & 0x04)
7639 76a66253 j_mayer
            a = 'G';
7640 76a66253 j_mayer
        else if (env->crf[i] & 0x02)
7641 76a66253 j_mayer
            a = 'E';
7642 7fe48483 bellard
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
7643 76a66253 j_mayer
    }
7644 6b542af7 j_mayer
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
7645 3fc6c082 bellard
    for (i = 0; i < 32; i++) {
7646 3fc6c082 bellard
        if ((i & (RFPL - 1)) == 0)
7647 3fc6c082 bellard
            cpu_fprintf(f, "FPR%02d", i);
7648 26a76461 bellard
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
7649 3fc6c082 bellard
        if ((i & (RFPL - 1)) == (RFPL - 1))
7650 7fe48483 bellard
            cpu_fprintf(f, "\n");
7651 79aceca5 bellard
    }
7652 f2e63a42 j_mayer
#if !defined(CONFIG_USER_ONLY)
7653 6b542af7 j_mayer
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
7654 3fc6c082 bellard
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
7655 f2e63a42 j_mayer
#endif
7656 79aceca5 bellard
7657 3fc6c082 bellard
#undef RGPL
7658 3fc6c082 bellard
#undef RFPL
7659 79aceca5 bellard
}
7660 79aceca5 bellard
7661 76a66253 j_mayer
void cpu_dump_statistics (CPUState *env, FILE*f,
7662 76a66253 j_mayer
                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7663 76a66253 j_mayer
                          int flags)
7664 76a66253 j_mayer
{
7665 76a66253 j_mayer
#if defined(DO_PPC_STATISTICS)
7666 76a66253 j_mayer
    opc_handler_t **t1, **t2, **t3, *handler;
7667 76a66253 j_mayer
    int op1, op2, op3;
7668 76a66253 j_mayer
7669 76a66253 j_mayer
    t1 = env->opcodes;
7670 76a66253 j_mayer
    for (op1 = 0; op1 < 64; op1++) {
7671 76a66253 j_mayer
        handler = t1[op1];
7672 76a66253 j_mayer
        if (is_indirect_opcode(handler)) {
7673 76a66253 j_mayer
            t2 = ind_table(handler);
7674 76a66253 j_mayer
            for (op2 = 0; op2 < 32; op2++) {
7675 76a66253 j_mayer
                handler = t2[op2];
7676 76a66253 j_mayer
                if (is_indirect_opcode(handler)) {
7677 76a66253 j_mayer
                    t3 = ind_table(handler);
7678 76a66253 j_mayer
                    for (op3 = 0; op3 < 32; op3++) {
7679 76a66253 j_mayer
                        handler = t3[op3];
7680 76a66253 j_mayer
                        if (handler->count == 0)
7681 76a66253 j_mayer
                            continue;
7682 76a66253 j_mayer
                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
7683 76a66253 j_mayer
                                    "%016llx %lld\n",
7684 76a66253 j_mayer
                                    op1, op2, op3, op1, (op3 << 5) | op2,
7685 76a66253 j_mayer
                                    handler->oname,
7686 76a66253 j_mayer
                                    handler->count, handler->count);
7687 76a66253 j_mayer
                    }
7688 76a66253 j_mayer
                } else {
7689 76a66253 j_mayer
                    if (handler->count == 0)
7690 76a66253 j_mayer
                        continue;
7691 76a66253 j_mayer
                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
7692 76a66253 j_mayer
                                "%016llx %lld\n",
7693 76a66253 j_mayer
                                op1, op2, op1, op2, handler->oname,
7694 76a66253 j_mayer
                                handler->count, handler->count);
7695 76a66253 j_mayer
                }
7696 76a66253 j_mayer
            }
7697 76a66253 j_mayer
        } else {
7698 76a66253 j_mayer
            if (handler->count == 0)
7699 76a66253 j_mayer
                continue;
7700 76a66253 j_mayer
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016llx %lld\n",
7701 76a66253 j_mayer
                        op1, op1, handler->oname,
7702 76a66253 j_mayer
                        handler->count, handler->count);
7703 76a66253 j_mayer
        }
7704 76a66253 j_mayer
    }
7705 76a66253 j_mayer
#endif
7706 76a66253 j_mayer
}
7707 76a66253 j_mayer
7708 9a64fbe4 bellard
/*****************************************************************************/
7709 2cfc5f17 ths
static always_inline void gen_intermediate_code_internal (CPUState *env,
7710 2cfc5f17 ths
                                                          TranslationBlock *tb,
7711 2cfc5f17 ths
                                                          int search_pc)
7712 79aceca5 bellard
{
7713 9fddaa0c bellard
    DisasContext ctx, *ctxp = &ctx;
7714 79aceca5 bellard
    opc_handler_t **table, *handler;
7715 0fa85d43 bellard
    target_ulong pc_start;
7716 79aceca5 bellard
    uint16_t *gen_opc_end;
7717 a1d1bb31 aliguori
    CPUBreakpoint *bp;
7718 79aceca5 bellard
    int j, lj = -1;
7719 2e70f6ef pbrook
    int num_insns;
7720 2e70f6ef pbrook
    int max_insns;
7721 79aceca5 bellard
7722 79aceca5 bellard
    pc_start = tb->pc;
7723 79aceca5 bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7724 7c58044c j_mayer
#if defined(OPTIMIZE_FPRF_UPDATE)
7725 7c58044c j_mayer
    gen_fprf_ptr = gen_fprf_buf;
7726 7c58044c j_mayer
#endif
7727 046d6672 bellard
    ctx.nip = pc_start;
7728 79aceca5 bellard
    ctx.tb = tb;
7729 e1833e1f j_mayer
    ctx.exception = POWERPC_EXCP_NONE;
7730 3fc6c082 bellard
    ctx.spr_cb = env->spr_cb;
7731 76db3ba4 aurel32
    ctx.mem_idx = env->mmu_idx;
7732 76db3ba4 aurel32
    ctx.access_type = -1;
7733 76db3ba4 aurel32
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
7734 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
7735 d9bce9d9 j_mayer
    ctx.sf_mode = msr_sf;
7736 9a64fbe4 bellard
#endif
7737 3cc62370 bellard
    ctx.fpu_enabled = msr_fp;
7738 a9d9eb8f j_mayer
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
7739 d26bfc9a j_mayer
        ctx.spe_enabled = msr_spe;
7740 d26bfc9a j_mayer
    else
7741 d26bfc9a j_mayer
        ctx.spe_enabled = 0;
7742 a9d9eb8f j_mayer
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
7743 a9d9eb8f j_mayer
        ctx.altivec_enabled = msr_vr;
7744 a9d9eb8f j_mayer
    else
7745 a9d9eb8f j_mayer
        ctx.altivec_enabled = 0;
7746 d26bfc9a j_mayer
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
7747 8cbcb4fa aurel32
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
7748 d26bfc9a j_mayer
    else
7749 8cbcb4fa aurel32
        ctx.singlestep_enabled = 0;
7750 d26bfc9a j_mayer
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
7751 8cbcb4fa aurel32
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
7752 8cbcb4fa aurel32
    if (unlikely(env->singlestep_enabled))
7753 8cbcb4fa aurel32
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
7754 3fc6c082 bellard
#if defined (DO_SINGLE_STEP) && 0
7755 9a64fbe4 bellard
    /* Single step trace mode */
7756 9a64fbe4 bellard
    msr_se = 1;
7757 9a64fbe4 bellard
#endif
7758 2e70f6ef pbrook
    num_insns = 0;
7759 2e70f6ef pbrook
    max_insns = tb->cflags & CF_COUNT_MASK;
7760 2e70f6ef pbrook
    if (max_insns == 0)
7761 2e70f6ef pbrook
        max_insns = CF_COUNT_MASK;
7762 2e70f6ef pbrook
7763 2e70f6ef pbrook
    gen_icount_start();
7764 9a64fbe4 bellard
    /* Set env in case of segfault during code fetch */
7765 e1833e1f j_mayer
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
7766 c0ce998e aliguori
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
7767 c0ce998e aliguori
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
7768 a1d1bb31 aliguori
                if (bp->pc == ctx.nip) {
7769 5fafdf24 ths
                    gen_update_nip(&ctx, ctx.nip);
7770 64adab3f aurel32
                    gen_helper_raise_debug();
7771 ea4e754f bellard
                    break;
7772 ea4e754f bellard
                }
7773 ea4e754f bellard
            }
7774 ea4e754f bellard
        }
7775 76a66253 j_mayer
        if (unlikely(search_pc)) {
7776 79aceca5 bellard
            j = gen_opc_ptr - gen_opc_buf;
7777 79aceca5 bellard
            if (lj < j) {
7778 79aceca5 bellard
                lj++;
7779 79aceca5 bellard
                while (lj < j)
7780 79aceca5 bellard
                    gen_opc_instr_start[lj++] = 0;
7781 046d6672 bellard
                gen_opc_pc[lj] = ctx.nip;
7782 79aceca5 bellard
                gen_opc_instr_start[lj] = 1;
7783 2e70f6ef pbrook
                gen_opc_icount[lj] = num_insns;
7784 79aceca5 bellard
            }
7785 79aceca5 bellard
        }
7786 9fddaa0c bellard
#if defined PPC_DEBUG_DISAS
7787 9fddaa0c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
7788 79aceca5 bellard
            fprintf(logfile, "----------------\n");
7789 1b9eb036 j_mayer
            fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
7790 76db3ba4 aurel32
                    ctx.nip, ctx.mem_idx, (int)msr_ir);
7791 9a64fbe4 bellard
        }
7792 9a64fbe4 bellard
#endif
7793 2e70f6ef pbrook
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
7794 2e70f6ef pbrook
            gen_io_start();
7795 76db3ba4 aurel32
        if (unlikely(ctx.le_mode)) {
7796 056401ea j_mayer
            ctx.opcode = bswap32(ldl_code(ctx.nip));
7797 056401ea j_mayer
        } else {
7798 056401ea j_mayer
            ctx.opcode = ldl_code(ctx.nip);
7799 111bfab3 bellard
        }
7800 9fddaa0c bellard
#if defined PPC_DEBUG_DISAS
7801 9fddaa0c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
7802 111bfab3 bellard
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
7803 9a64fbe4 bellard
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
7804 056401ea j_mayer
                    opc3(ctx.opcode), little_endian ? "little" : "big");
7805 79aceca5 bellard
        }
7806 79aceca5 bellard
#endif
7807 046d6672 bellard
        ctx.nip += 4;
7808 3fc6c082 bellard
        table = env->opcodes;
7809 2e70f6ef pbrook
        num_insns++;
7810 79aceca5 bellard
        handler = table[opc1(ctx.opcode)];
7811 79aceca5 bellard
        if (is_indirect_opcode(handler)) {
7812 79aceca5 bellard
            table = ind_table(handler);
7813 79aceca5 bellard
            handler = table[opc2(ctx.opcode)];
7814 79aceca5 bellard
            if (is_indirect_opcode(handler)) {
7815 79aceca5 bellard
                table = ind_table(handler);
7816 79aceca5 bellard
                handler = table[opc3(ctx.opcode)];
7817 79aceca5 bellard
            }
7818 79aceca5 bellard
        }
7819 79aceca5 bellard
        /* Is opcode *REALLY* valid ? */
7820 76a66253 j_mayer
        if (unlikely(handler->handler == &gen_invalid)) {
7821 4a057712 j_mayer
            if (loglevel != 0) {
7822 76a66253 j_mayer
                fprintf(logfile, "invalid/unsupported opcode: "
7823 6b542af7 j_mayer
                        "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
7824 76a66253 j_mayer
                        opc1(ctx.opcode), opc2(ctx.opcode),
7825 0411a972 j_mayer
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
7826 4b3686fa bellard
            } else {
7827 4b3686fa bellard
                printf("invalid/unsupported opcode: "
7828 6b542af7 j_mayer
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
7829 4b3686fa bellard
                       opc1(ctx.opcode), opc2(ctx.opcode),
7830 0411a972 j_mayer
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
7831 4b3686fa bellard
            }
7832 76a66253 j_mayer
        } else {
7833 76a66253 j_mayer
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
7834 4a057712 j_mayer
                if (loglevel != 0) {
7835 79aceca5 bellard
                    fprintf(logfile, "invalid bits: %08x for opcode: "
7836 6b542af7 j_mayer
                            "%02x - %02x - %02x (%08x) " ADDRX "\n",
7837 79aceca5 bellard
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
7838 79aceca5 bellard
                            opc2(ctx.opcode), opc3(ctx.opcode),
7839 046d6672 bellard
                            ctx.opcode, ctx.nip - 4);
7840 9a64fbe4 bellard
                } else {
7841 9a64fbe4 bellard
                    printf("invalid bits: %08x for opcode: "
7842 6b542af7 j_mayer
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
7843 76a66253 j_mayer
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
7844 76a66253 j_mayer
                           opc2(ctx.opcode), opc3(ctx.opcode),
7845 046d6672 bellard
                           ctx.opcode, ctx.nip - 4);
7846 76a66253 j_mayer
                }
7847 e1833e1f j_mayer
                GEN_EXCP_INVAL(ctxp);
7848 4b3686fa bellard
                break;
7849 79aceca5 bellard
            }
7850 79aceca5 bellard
        }
7851 4b3686fa bellard
        (*(handler->handler))(&ctx);
7852 76a66253 j_mayer
#if defined(DO_PPC_STATISTICS)
7853 76a66253 j_mayer
        handler->count++;
7854 76a66253 j_mayer
#endif
7855 9a64fbe4 bellard
        /* Check trace mode exceptions */
7856 8cbcb4fa aurel32
        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
7857 8cbcb4fa aurel32
                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
7858 8cbcb4fa aurel32
                     ctx.exception != POWERPC_SYSCALL &&
7859 8cbcb4fa aurel32
                     ctx.exception != POWERPC_EXCP_TRAP &&
7860 8cbcb4fa aurel32
                     ctx.exception != POWERPC_EXCP_BRANCH)) {
7861 e1833e1f j_mayer
            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
7862 d26bfc9a j_mayer
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
7863 2e70f6ef pbrook
                            (env->singlestep_enabled) ||
7864 2e70f6ef pbrook
                            num_insns >= max_insns)) {
7865 d26bfc9a j_mayer
            /* if we reach a page boundary or are single stepping, stop
7866 d26bfc9a j_mayer
             * generation
7867 d26bfc9a j_mayer
             */
7868 8dd4983c bellard
            break;
7869 76a66253 j_mayer
        }
7870 3fc6c082 bellard
#if defined (DO_SINGLE_STEP)
7871 3fc6c082 bellard
        break;
7872 3fc6c082 bellard
#endif
7873 3fc6c082 bellard
    }
7874 2e70f6ef pbrook
    if (tb->cflags & CF_LAST_IO)
7875 2e70f6ef pbrook
        gen_io_end();
7876 e1833e1f j_mayer
    if (ctx.exception == POWERPC_EXCP_NONE) {
7877 c1942362 bellard
        gen_goto_tb(&ctx, 0, ctx.nip);
7878 e1833e1f j_mayer
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
7879 8cbcb4fa aurel32
        if (unlikely(env->singlestep_enabled)) {
7880 8cbcb4fa aurel32
            gen_update_nip(&ctx, ctx.nip);
7881 64adab3f aurel32
            gen_helper_raise_debug();
7882 8cbcb4fa aurel32
        }
7883 76a66253 j_mayer
        /* Generate the return instruction */
7884 57fec1fe bellard
        tcg_gen_exit_tb(0);
7885 9a64fbe4 bellard
    }
7886 2e70f6ef pbrook
    gen_icount_end(tb, num_insns);
7887 79aceca5 bellard
    *gen_opc_ptr = INDEX_op_end;
7888 76a66253 j_mayer
    if (unlikely(search_pc)) {
7889 9a64fbe4 bellard
        j = gen_opc_ptr - gen_opc_buf;
7890 9a64fbe4 bellard
        lj++;
7891 9a64fbe4 bellard
        while (lj <= j)
7892 9a64fbe4 bellard
            gen_opc_instr_start[lj++] = 0;
7893 9a64fbe4 bellard
    } else {
7894 046d6672 bellard
        tb->size = ctx.nip - pc_start;
7895 2e70f6ef pbrook
        tb->icount = num_insns;
7896 9a64fbe4 bellard
    }
7897 d9bce9d9 j_mayer
#if defined(DEBUG_DISAS)
7898 9fddaa0c bellard
    if (loglevel & CPU_LOG_TB_CPU) {
7899 9a64fbe4 bellard
        fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
7900 7fe48483 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
7901 9fddaa0c bellard
    }
7902 9fddaa0c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
7903 76a66253 j_mayer
        int flags;
7904 237c0af0 j_mayer
        flags = env->bfd_mach;
7905 76db3ba4 aurel32
        flags |= ctx.le_mode << 16;
7906 0fa85d43 bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
7907 76a66253 j_mayer
        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
7908 79aceca5 bellard
        fprintf(logfile, "\n");
7909 9fddaa0c bellard
    }
7910 79aceca5 bellard
#endif
7911 79aceca5 bellard
}
7912 79aceca5 bellard
7913 2cfc5f17 ths
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
7914 79aceca5 bellard
{
7915 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 0);
7916 79aceca5 bellard
}
7917 79aceca5 bellard
7918 2cfc5f17 ths
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
7919 79aceca5 bellard
{
7920 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 1);
7921 79aceca5 bellard
}
7922 d2856f1a aurel32
7923 d2856f1a aurel32
void gen_pc_load(CPUState *env, TranslationBlock *tb,
7924 d2856f1a aurel32
                unsigned long searched_pc, int pc_pos, void *puc)
7925 d2856f1a aurel32
{
7926 d2856f1a aurel32
    env->nip = gen_opc_pc[pc_pos];
7927 d2856f1a aurel32
}