Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ a456d59c

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

7140 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
7141 0487d6a8 j_mayer
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
7142 0487d6a8 j_mayer
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
7143 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
7144 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
7145 0487d6a8 j_mayer
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
7146 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
7147 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
7148 0487d6a8 j_mayer
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
7149 0487d6a8 j_mayer
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
7150 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
7151 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
7152 0487d6a8 j_mayer
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
7153 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
7154 0487d6a8 j_mayer

7155 0487d6a8 j_mayer
GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
7156 0487d6a8 j_mayer
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
7157 0487d6a8 j_mayer
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
7158 0487d6a8 j_mayer
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
7159 0487d6a8 j_mayer
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
7160 0487d6a8 j_mayer
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
7161 0487d6a8 j_mayer

7162 0487d6a8 j_mayer
GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
7163 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
7164 0487d6a8 j_mayer
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
7165 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
7166 0487d6a8 j_mayer
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
7167 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
7168 0487d6a8 j_mayer
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
7169 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
7170 0487d6a8 j_mayer
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
7171 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
7172 0487d6a8 j_mayer
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
7173 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
7174 0487d6a8 j_mayer

7175 0487d6a8 j_mayer
GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
7176 0487d6a8 j_mayer
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
7177 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
7178 0487d6a8 j_mayer
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
7179 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
7180 0487d6a8 j_mayer

7181 0487d6a8 j_mayer
GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
7182 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
7183 0487d6a8 j_mayer
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
7184 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
7185 0487d6a8 j_mayer
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
7186 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
7187 0487d6a8 j_mayer
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
7188 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
7189 0487d6a8 j_mayer
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
7190 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
7191 0487d6a8 j_mayer
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
7192 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
7193 0487d6a8 j_mayer

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