Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ 57be80f9

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

7554 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
7555 0487d6a8 j_mayer
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
7556 0487d6a8 j_mayer
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
7557 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
7558 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
7559 0487d6a8 j_mayer
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
7560 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
7561 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
7562 0487d6a8 j_mayer
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
7563 0487d6a8 j_mayer
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
7564 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
7565 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
7566 0487d6a8 j_mayer
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
7567 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
7568 0487d6a8 j_mayer

7569 0487d6a8 j_mayer
GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
7570 0487d6a8 j_mayer
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
7571 0487d6a8 j_mayer
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
7572 0487d6a8 j_mayer
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
7573 0487d6a8 j_mayer
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
7574 0487d6a8 j_mayer
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
7575 0487d6a8 j_mayer

7576 0487d6a8 j_mayer
GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
7577 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
7578 0487d6a8 j_mayer
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
7579 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
7580 0487d6a8 j_mayer
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
7581 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
7582 0487d6a8 j_mayer
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
7583 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
7584 0487d6a8 j_mayer
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
7585 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
7586 0487d6a8 j_mayer
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
7587 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
7588 0487d6a8 j_mayer

7589 0487d6a8 j_mayer
GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
7590 0487d6a8 j_mayer
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
7591 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
7592 0487d6a8 j_mayer
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
7593 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
7594 0487d6a8 j_mayer

7595 0487d6a8 j_mayer
GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
7596 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
7597 0487d6a8 j_mayer
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
7598 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
7599 0487d6a8 j_mayer
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
7600 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
7601 0487d6a8 j_mayer
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
7602 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
7603 0487d6a8 j_mayer
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
7604 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
7605 0487d6a8 j_mayer
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
7606 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
7607 0487d6a8 j_mayer

7608 0487d6a8 j_mayer
GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, PPC_SPE);
7609 0487d6a8 j_mayer
GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, PPC_SPE);
7610 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0x00000000, PPC_SPE);
7611 0487d6a8 j_mayer
GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, PPC_SPE);
7612 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0x00000000, PPC_SPE);
7613 0487d6a8 j_mayer
#endif
7614 0487d6a8 j_mayer
7615 0487d6a8 j_mayer
/***                      SPE floating-point extension                     ***/
7616 1c97856d aurel32
#if defined(TARGET_PPC64)
7617 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
7618 b068d6a7 j_mayer
static always_inline void gen_##name (DisasContext *ctx)                      \
7619 0487d6a8 j_mayer
{                                                                             \
7620 1c97856d aurel32
    TCGv_i32 t0;                                                              \
7621 1c97856d aurel32
    TCGv t1;                                                                  \
7622 1c97856d aurel32
    t0 = tcg_temp_new_i32();                                                  \
7623 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
7624 1c97856d aurel32
    gen_helper_##name(t0, t0);                                                \
7625 1c97856d aurel32
    t1 = tcg_temp_new();                                                      \
7626 1c97856d aurel32
    tcg_gen_extu_i32_tl(t1, t0);                                              \
7627 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7628 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7629 1c97856d aurel32
                    0xFFFFFFFF00000000ULL);                                   \
7630 1c97856d aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
7631 1c97856d aurel32
    tcg_temp_free(t1);                                                        \
7632 0487d6a8 j_mayer
}
7633 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
7634 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7635 1c97856d aurel32
{                                                                             \
7636 1c97856d aurel32
    TCGv_i32 t0;                                                              \
7637 1c97856d aurel32
    TCGv t1;                                                                  \
7638 1c97856d aurel32
    t0 = tcg_temp_new_i32();                                                  \
7639 1c97856d aurel32
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
7640 1c97856d aurel32
    t1 = tcg_temp_new();                                                      \
7641 1c97856d aurel32
    tcg_gen_extu_i32_tl(t1, t0);                                              \
7642 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7643 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7644 1c97856d aurel32
                    0xFFFFFFFF00000000ULL);                                   \
7645 1c97856d aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1);    \
7646 1c97856d aurel32
    tcg_temp_free(t1);                                                        \
7647 1c97856d aurel32
}
7648 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
7649 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7650 1c97856d aurel32
{                                                                             \
7651 1c97856d aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();                                         \
7652 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]);                       \
7653 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
7654 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7655 1c97856d aurel32
}
7656 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
7657 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7658 1c97856d aurel32
{                                                                             \
7659 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7660 1c97856d aurel32
}
7661 1c97856d aurel32
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
7662 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7663 57951c27 aurel32
{                                                                             \
7664 1c97856d aurel32
    TCGv_i32 t0, t1;                                                          \
7665 1c97856d aurel32
    TCGv_i64 t2;                                                              \
7666 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7667 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7668 57951c27 aurel32
        return;                                                               \
7669 57951c27 aurel32
    }                                                                         \
7670 1c97856d aurel32
    t0 = tcg_temp_new_i32();                                                  \
7671 1c97856d aurel32
    t1 = tcg_temp_new_i32();                                                  \
7672 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
7673 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
7674 1c97856d aurel32
    gen_helper_##name(t0, t0, t1);                                            \
7675 1c97856d aurel32
    tcg_temp_free_i32(t1);                                                    \
7676 1c97856d aurel32
    t2 = tcg_temp_new();                                                      \
7677 1c97856d aurel32
    tcg_gen_extu_i32_tl(t2, t0);                                              \
7678 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7679 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)],       \
7680 1c97856d aurel32
                    0xFFFFFFFF00000000ULL);                                   \
7681 1c97856d aurel32
    tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2);    \
7682 1c97856d aurel32
    tcg_temp_free(t2);                                                        \
7683 57951c27 aurel32
}
7684 1c97856d aurel32
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
7685 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7686 57951c27 aurel32
{                                                                             \
7687 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7688 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7689 57951c27 aurel32
        return;                                                               \
7690 57951c27 aurel32
    }                                                                         \
7691 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],     \
7692 1c97856d aurel32
                      cpu_gpr[rB(ctx->opcode)]);                              \
7693 57951c27 aurel32
}
7694 1c97856d aurel32
#define GEN_SPEFPUOP_COMP_32(name)                                            \
7695 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7696 57951c27 aurel32
{                                                                             \
7697 1c97856d aurel32
    TCGv_i32 t0, t1;                                                          \
7698 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7699 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7700 57951c27 aurel32
        return;                                                               \
7701 57951c27 aurel32
    }                                                                         \
7702 1c97856d aurel32
    t0 = tcg_temp_new_i32();                                                  \
7703 1c97856d aurel32
    t1 = tcg_temp_new_i32();                                                  \
7704 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);                       \
7705 1c97856d aurel32
    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);                       \
7706 1c97856d aurel32
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
7707 1c97856d aurel32
    tcg_temp_free_i32(t0);                                                    \
7708 1c97856d aurel32
    tcg_temp_free_i32(t1);                                                    \
7709 1c97856d aurel32
}
7710 1c97856d aurel32
#define GEN_SPEFPUOP_COMP_64(name)                                            \
7711 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7712 1c97856d aurel32
{                                                                             \
7713 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7714 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7715 1c97856d aurel32
        return;                                                               \
7716 1c97856d aurel32
    }                                                                         \
7717 1c97856d aurel32
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
7718 1c97856d aurel32
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7719 1c97856d aurel32
}
7720 1c97856d aurel32
#else
7721 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_32_32(name)                                         \
7722 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7723 1c97856d aurel32
{                                                                             \
7724 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7725 57951c27 aurel32
}
7726 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_32_64(name)                                         \
7727 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7728 1c97856d aurel32
{                                                                             \
7729 1c97856d aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7730 1c97856d aurel32
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
7731 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0);                          \
7732 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7733 1c97856d aurel32
}
7734 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_64_32(name)                                         \
7735 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7736 1c97856d aurel32
{                                                                             \
7737 1c97856d aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7738 1c97856d aurel32
    gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]);                          \
7739 1c97856d aurel32
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7740 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7741 1c97856d aurel32
}
7742 1c97856d aurel32
#define GEN_SPEFPUOP_CONV_64_64(name)                                         \
7743 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7744 1c97856d aurel32
{                                                                             \
7745 1c97856d aurel32
    TCGv_i64 t0 = tcg_temp_new_i64();                                         \
7746 1c97856d aurel32
    gen_load_gpr64(t0, rB(ctx->opcode));                                      \
7747 1c97856d aurel32
    gen_helper_##name(t0, t0);                                                \
7748 1c97856d aurel32
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7749 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7750 1c97856d aurel32
}
7751 1c97856d aurel32
#define GEN_SPEFPUOP_ARITH2_32_32(name)                                       \
7752 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7753 1c97856d aurel32
{                                                                             \
7754 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7755 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7756 1c97856d aurel32
        return;                                                               \
7757 1c97856d aurel32
    }                                                                         \
7758 1c97856d aurel32
    gen_helper_##name(cpu_gpr[rD(ctx->opcode)],                               \
7759 1c97856d aurel32
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7760 1c97856d aurel32
}
7761 1c97856d aurel32
#define GEN_SPEFPUOP_ARITH2_64_64(name)                                       \
7762 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7763 1c97856d aurel32
{                                                                             \
7764 1c97856d aurel32
    TCGv_i64 t0, t1;                                                          \
7765 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7766 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7767 1c97856d aurel32
        return;                                                               \
7768 1c97856d aurel32
    }                                                                         \
7769 1c97856d aurel32
    t0 = tcg_temp_new_i64();                                                  \
7770 1c97856d aurel32
    t1 = tcg_temp_new_i64();                                                  \
7771 1c97856d aurel32
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
7772 1c97856d aurel32
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
7773 1c97856d aurel32
    gen_helper_##name(t0, t0, t1);                                            \
7774 1c97856d aurel32
    gen_store_gpr64(rD(ctx->opcode), t0);                                     \
7775 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7776 1c97856d aurel32
    tcg_temp_free_i64(t1);                                                    \
7777 1c97856d aurel32
}
7778 1c97856d aurel32
#define GEN_SPEFPUOP_COMP_32(name)                                            \
7779 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7780 1c97856d aurel32
{                                                                             \
7781 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7782 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7783 1c97856d aurel32
        return;                                                               \
7784 1c97856d aurel32
    }                                                                         \
7785 1c97856d aurel32
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)],                             \
7786 1c97856d aurel32
                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);    \
7787 1c97856d aurel32
}
7788 1c97856d aurel32
#define GEN_SPEFPUOP_COMP_64(name)                                            \
7789 1c97856d aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
7790 1c97856d aurel32
{                                                                             \
7791 1c97856d aurel32
    TCGv_i64 t0, t1;                                                          \
7792 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
7793 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);                                 \
7794 1c97856d aurel32
        return;                                                               \
7795 1c97856d aurel32
    }                                                                         \
7796 1c97856d aurel32
    t0 = tcg_temp_new_i64();                                                  \
7797 1c97856d aurel32
    t1 = tcg_temp_new_i64();                                                  \
7798 1c97856d aurel32
    gen_load_gpr64(t0, rA(ctx->opcode));                                      \
7799 1c97856d aurel32
    gen_load_gpr64(t1, rB(ctx->opcode));                                      \
7800 1c97856d aurel32
    gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1);                    \
7801 1c97856d aurel32
    tcg_temp_free_i64(t0);                                                    \
7802 1c97856d aurel32
    tcg_temp_free_i64(t1);                                                    \
7803 1c97856d aurel32
}
7804 1c97856d aurel32
#endif
7805 57951c27 aurel32
7806 0487d6a8 j_mayer
/* Single precision floating-point vectors operations */
7807 0487d6a8 j_mayer
/* Arithmetic */
7808 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
7809 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(evfssub);
7810 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
7811 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
7812 1c97856d aurel32
static always_inline void gen_evfsabs (DisasContext *ctx)
7813 1c97856d aurel32
{
7814 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7815 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);
7816 1c97856d aurel32
        return;
7817 1c97856d aurel32
    }
7818 1c97856d aurel32
#if defined(TARGET_PPC64)
7819 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
7820 1c97856d aurel32
#else
7821 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
7822 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7823 1c97856d aurel32
#endif
7824 1c97856d aurel32
}
7825 1c97856d aurel32
static always_inline void gen_evfsnabs (DisasContext *ctx)
7826 1c97856d aurel32
{
7827 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7828 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);
7829 1c97856d aurel32
        return;
7830 1c97856d aurel32
    }
7831 1c97856d aurel32
#if defined(TARGET_PPC64)
7832 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7833 1c97856d aurel32
#else
7834 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7835 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7836 1c97856d aurel32
#endif
7837 1c97856d aurel32
}
7838 1c97856d aurel32
static always_inline void gen_evfsneg (DisasContext *ctx)
7839 1c97856d aurel32
{
7840 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7841 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);
7842 1c97856d aurel32
        return;
7843 1c97856d aurel32
    }
7844 1c97856d aurel32
#if defined(TARGET_PPC64)
7845 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7846 1c97856d aurel32
#else
7847 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7848 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7849 1c97856d aurel32
#endif
7850 1c97856d aurel32
}
7851 1c97856d aurel32
7852 0487d6a8 j_mayer
/* Conversion */
7853 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfscfui);
7854 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfscfsi);
7855 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfscfuf);
7856 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfscfsf);
7857 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctui);
7858 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctsi);
7859 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctuf);
7860 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctsf);
7861 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
7862 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
7863 1c97856d aurel32
7864 0487d6a8 j_mayer
/* Comparison */
7865 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfscmpgt);
7866 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfscmplt);
7867 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfscmpeq);
7868 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfststgt);
7869 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfststlt);
7870 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(evfststeq);
7871 0487d6a8 j_mayer
7872 0487d6a8 j_mayer
/* Opcodes definitions */
7873 0487d6a8 j_mayer
GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
7874 0487d6a8 j_mayer
GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
7875 0487d6a8 j_mayer
GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
7876 0487d6a8 j_mayer
GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
7877 0487d6a8 j_mayer
GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
7878 0487d6a8 j_mayer
GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
7879 0487d6a8 j_mayer
GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
7880 0487d6a8 j_mayer
GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
7881 0487d6a8 j_mayer
GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
7882 0487d6a8 j_mayer
GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
7883 0487d6a8 j_mayer
GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
7884 0487d6a8 j_mayer
GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
7885 0487d6a8 j_mayer
GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
7886 0487d6a8 j_mayer
GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
7887 0487d6a8 j_mayer
7888 0487d6a8 j_mayer
/* Single precision floating-point operations */
7889 0487d6a8 j_mayer
/* Arithmetic */
7890 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_32_32(efsadd);
7891 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_32_32(efssub);
7892 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_32_32(efsmul);
7893 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
7894 1c97856d aurel32
static always_inline void gen_efsabs (DisasContext *ctx)
7895 1c97856d aurel32
{
7896 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7897 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);
7898 1c97856d aurel32
        return;
7899 1c97856d aurel32
    }
7900 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
7901 1c97856d aurel32
}
7902 1c97856d aurel32
static always_inline void gen_efsnabs (DisasContext *ctx)
7903 1c97856d aurel32
{
7904 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7905 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);
7906 1c97856d aurel32
        return;
7907 1c97856d aurel32
    }
7908 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7909 1c97856d aurel32
}
7910 1c97856d aurel32
static always_inline void gen_efsneg (DisasContext *ctx)
7911 1c97856d aurel32
{
7912 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7913 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);
7914 1c97856d aurel32
        return;
7915 1c97856d aurel32
    }
7916 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7917 1c97856d aurel32
}
7918 1c97856d aurel32
7919 0487d6a8 j_mayer
/* Conversion */
7920 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efscfui);
7921 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efscfsi);
7922 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efscfuf);
7923 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efscfsf);
7924 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctui);
7925 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctsi);
7926 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctuf);
7927 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctsf);
7928 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctuiz);
7929 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_32(efsctsiz);
7930 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efscfd);
7931 1c97856d aurel32
7932 0487d6a8 j_mayer
/* Comparison */
7933 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efscmpgt);
7934 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efscmplt);
7935 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efscmpeq);
7936 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efststgt);
7937 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efststlt);
7938 1c97856d aurel32
GEN_SPEFPUOP_COMP_32(efststeq);
7939 0487d6a8 j_mayer
7940 0487d6a8 j_mayer
/* Opcodes definitions */
7941 05332d70 j_mayer
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
7942 0487d6a8 j_mayer
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
7943 0487d6a8 j_mayer
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
7944 0487d6a8 j_mayer
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
7945 0487d6a8 j_mayer
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
7946 0487d6a8 j_mayer
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
7947 0487d6a8 j_mayer
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
7948 0487d6a8 j_mayer
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
7949 0487d6a8 j_mayer
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
7950 0487d6a8 j_mayer
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
7951 9ceb2a77 ths
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
7952 9ceb2a77 ths
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
7953 0487d6a8 j_mayer
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
7954 0487d6a8 j_mayer
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
7955 0487d6a8 j_mayer
7956 0487d6a8 j_mayer
/* Double precision floating-point operations */
7957 0487d6a8 j_mayer
/* Arithmetic */
7958 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(efdadd);
7959 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(efdsub);
7960 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(efdmul);
7961 1c97856d aurel32
GEN_SPEFPUOP_ARITH2_64_64(efddiv);
7962 1c97856d aurel32
static always_inline void gen_efdabs (DisasContext *ctx)
7963 1c97856d aurel32
{
7964 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7965 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);
7966 1c97856d aurel32
        return;
7967 1c97856d aurel32
    }
7968 1c97856d aurel32
#if defined(TARGET_PPC64)
7969 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
7970 1c97856d aurel32
#else
7971 1c97856d aurel32
    tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7972 1c97856d aurel32
#endif
7973 1c97856d aurel32
}
7974 1c97856d aurel32
static always_inline void gen_efdnabs (DisasContext *ctx)
7975 1c97856d aurel32
{
7976 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7977 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);
7978 1c97856d aurel32
        return;
7979 1c97856d aurel32
    }
7980 1c97856d aurel32
#if defined(TARGET_PPC64)
7981 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7982 1c97856d aurel32
#else
7983 1c97856d aurel32
    tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7984 1c97856d aurel32
#endif
7985 1c97856d aurel32
}
7986 1c97856d aurel32
static always_inline void gen_efdneg (DisasContext *ctx)
7987 1c97856d aurel32
{
7988 1c97856d aurel32
    if (unlikely(!ctx->spe_enabled)) {
7989 e06fcd75 aurel32
        gen_exception(ctx, POWERPC_EXCP_APU);
7990 1c97856d aurel32
        return;
7991 1c97856d aurel32
    }
7992 1c97856d aurel32
#if defined(TARGET_PPC64)
7993 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7994 1c97856d aurel32
#else
7995 1c97856d aurel32
    tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7996 1c97856d aurel32
#endif
7997 1c97856d aurel32
}
7998 1c97856d aurel32
7999 0487d6a8 j_mayer
/* Conversion */
8000 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfui);
8001 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfsi);
8002 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfuf);
8003 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfsf);
8004 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctui);
8005 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctsi);
8006 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctuf);
8007 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctsf);
8008 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctuiz);
8009 1c97856d aurel32
GEN_SPEFPUOP_CONV_32_64(efdctsiz);
8010 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_32(efdcfs);
8011 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(efdcfuid);
8012 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(efdcfsid);
8013 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(efdctuidz);
8014 1c97856d aurel32
GEN_SPEFPUOP_CONV_64_64(efdctsidz);
8015 0487d6a8 j_mayer
8016 0487d6a8 j_mayer
/* Comparison */
8017 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdcmpgt);
8018 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdcmplt);
8019 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdcmpeq);
8020 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdtstgt);
8021 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdtstlt);
8022 1c97856d aurel32
GEN_SPEFPUOP_COMP_64(efdtsteq);
8023 0487d6a8 j_mayer
8024 0487d6a8 j_mayer
/* Opcodes definitions */
8025 0487d6a8 j_mayer
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
8026 0487d6a8 j_mayer
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
8027 0487d6a8 j_mayer
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
8028 0487d6a8 j_mayer
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
8029 0487d6a8 j_mayer
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
8030 0487d6a8 j_mayer
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
8031 0487d6a8 j_mayer
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
8032 0487d6a8 j_mayer
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
8033 0487d6a8 j_mayer
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
8034 0487d6a8 j_mayer
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
8035 0487d6a8 j_mayer
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
8036 0487d6a8 j_mayer
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
8037 0487d6a8 j_mayer
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
8038 0487d6a8 j_mayer
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
8039 0487d6a8 j_mayer
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
8040 0487d6a8 j_mayer
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
8041 0487d6a8 j_mayer
8042 79aceca5 bellard
/* End opcode list */
8043 79aceca5 bellard
GEN_OPCODE_MARK(end);
8044 79aceca5 bellard
8045 3fc6c082 bellard
#include "translate_init.c"
8046 0411a972 j_mayer
#include "helper_regs.h"
8047 79aceca5 bellard
8048 9a64fbe4 bellard
/*****************************************************************************/
8049 3fc6c082 bellard
/* Misc PowerPC helpers */
8050 36081602 j_mayer
void cpu_dump_state (CPUState *env, FILE *f,
8051 36081602 j_mayer
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8052 36081602 j_mayer
                     int flags)
8053 79aceca5 bellard
{
8054 3fc6c082 bellard
#define RGPL  4
8055 3fc6c082 bellard
#define RFPL  4
8056 3fc6c082 bellard
8057 79aceca5 bellard
    int i;
8058 79aceca5 bellard
8059 077fc206 j_mayer
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
8060 3d7b417e aurel32
                env->nip, env->lr, env->ctr, env->xer);
8061 6b542af7 j_mayer
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
8062 6b542af7 j_mayer
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
8063 d9bce9d9 j_mayer
#if !defined(NO_TIMER_DUMP)
8064 077fc206 j_mayer
    cpu_fprintf(f, "TB %08x %08x "
8065 76a66253 j_mayer
#if !defined(CONFIG_USER_ONLY)
8066 76a66253 j_mayer
                "DECR %08x"
8067 76a66253 j_mayer
#endif
8068 76a66253 j_mayer
                "\n",
8069 077fc206 j_mayer
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
8070 76a66253 j_mayer
#if !defined(CONFIG_USER_ONLY)
8071 76a66253 j_mayer
                , cpu_ppc_load_decr(env)
8072 76a66253 j_mayer
#endif
8073 76a66253 j_mayer
                );
8074 077fc206 j_mayer
#endif
8075 76a66253 j_mayer
    for (i = 0; i < 32; i++) {
8076 3fc6c082 bellard
        if ((i & (RGPL - 1)) == 0)
8077 3fc6c082 bellard
            cpu_fprintf(f, "GPR%02d", i);
8078 6b542af7 j_mayer
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
8079 3fc6c082 bellard
        if ((i & (RGPL - 1)) == (RGPL - 1))
8080 7fe48483 bellard
            cpu_fprintf(f, "\n");
8081 76a66253 j_mayer
    }
8082 3fc6c082 bellard
    cpu_fprintf(f, "CR ");
8083 76a66253 j_mayer
    for (i = 0; i < 8; i++)
8084 7fe48483 bellard
        cpu_fprintf(f, "%01x", env->crf[i]);
8085 7fe48483 bellard
    cpu_fprintf(f, "  [");
8086 76a66253 j_mayer
    for (i = 0; i < 8; i++) {
8087 76a66253 j_mayer
        char a = '-';
8088 76a66253 j_mayer
        if (env->crf[i] & 0x08)
8089 76a66253 j_mayer
            a = 'L';
8090 76a66253 j_mayer
        else if (env->crf[i] & 0x04)
8091 76a66253 j_mayer
            a = 'G';
8092 76a66253 j_mayer
        else if (env->crf[i] & 0x02)
8093 76a66253 j_mayer
            a = 'E';
8094 7fe48483 bellard
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
8095 76a66253 j_mayer
    }
8096 6b542af7 j_mayer
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
8097 3fc6c082 bellard
    for (i = 0; i < 32; i++) {
8098 3fc6c082 bellard
        if ((i & (RFPL - 1)) == 0)
8099 3fc6c082 bellard
            cpu_fprintf(f, "FPR%02d", i);
8100 26a76461 bellard
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
8101 3fc6c082 bellard
        if ((i & (RFPL - 1)) == (RFPL - 1))
8102 7fe48483 bellard
            cpu_fprintf(f, "\n");
8103 79aceca5 bellard
    }
8104 7889270a aurel32
    cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
8105 f2e63a42 j_mayer
#if !defined(CONFIG_USER_ONLY)
8106 6b542af7 j_mayer
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
8107 3fc6c082 bellard
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
8108 f2e63a42 j_mayer
#endif
8109 79aceca5 bellard
8110 3fc6c082 bellard
#undef RGPL
8111 3fc6c082 bellard
#undef RFPL
8112 79aceca5 bellard
}
8113 79aceca5 bellard
8114 76a66253 j_mayer
void cpu_dump_statistics (CPUState *env, FILE*f,
8115 76a66253 j_mayer
                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8116 76a66253 j_mayer
                          int flags)
8117 76a66253 j_mayer
{
8118 76a66253 j_mayer
#if defined(DO_PPC_STATISTICS)
8119 76a66253 j_mayer
    opc_handler_t **t1, **t2, **t3, *handler;
8120 76a66253 j_mayer
    int op1, op2, op3;
8121 76a66253 j_mayer
8122 76a66253 j_mayer
    t1 = env->opcodes;
8123 76a66253 j_mayer
    for (op1 = 0; op1 < 64; op1++) {
8124 76a66253 j_mayer
        handler = t1[op1];
8125 76a66253 j_mayer
        if (is_indirect_opcode(handler)) {
8126 76a66253 j_mayer
            t2 = ind_table(handler);
8127 76a66253 j_mayer
            for (op2 = 0; op2 < 32; op2++) {
8128 76a66253 j_mayer
                handler = t2[op2];
8129 76a66253 j_mayer
                if (is_indirect_opcode(handler)) {
8130 76a66253 j_mayer
                    t3 = ind_table(handler);
8131 76a66253 j_mayer
                    for (op3 = 0; op3 < 32; op3++) {
8132 76a66253 j_mayer
                        handler = t3[op3];
8133 76a66253 j_mayer
                        if (handler->count == 0)
8134 76a66253 j_mayer
                            continue;
8135 76a66253 j_mayer
                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
8136 76a66253 j_mayer
                                    "%016llx %lld\n",
8137 76a66253 j_mayer
                                    op1, op2, op3, op1, (op3 << 5) | op2,
8138 76a66253 j_mayer
                                    handler->oname,
8139 76a66253 j_mayer
                                    handler->count, handler->count);
8140 76a66253 j_mayer
                    }
8141 76a66253 j_mayer
                } else {
8142 76a66253 j_mayer
                    if (handler->count == 0)
8143 76a66253 j_mayer
                        continue;
8144 76a66253 j_mayer
                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
8145 76a66253 j_mayer
                                "%016llx %lld\n",
8146 76a66253 j_mayer
                                op1, op2, op1, op2, handler->oname,
8147 76a66253 j_mayer
                                handler->count, handler->count);
8148 76a66253 j_mayer
                }
8149 76a66253 j_mayer
            }
8150 76a66253 j_mayer
        } else {
8151 76a66253 j_mayer
            if (handler->count == 0)
8152 76a66253 j_mayer
                continue;
8153 76a66253 j_mayer
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016llx %lld\n",
8154 76a66253 j_mayer
                        op1, op1, handler->oname,
8155 76a66253 j_mayer
                        handler->count, handler->count);
8156 76a66253 j_mayer
        }
8157 76a66253 j_mayer
    }
8158 76a66253 j_mayer
#endif
8159 76a66253 j_mayer
}
8160 76a66253 j_mayer
8161 9a64fbe4 bellard
/*****************************************************************************/
8162 2cfc5f17 ths
static always_inline void gen_intermediate_code_internal (CPUState *env,
8163 2cfc5f17 ths
                                                          TranslationBlock *tb,
8164 2cfc5f17 ths
                                                          int search_pc)
8165 79aceca5 bellard
{
8166 9fddaa0c bellard
    DisasContext ctx, *ctxp = &ctx;
8167 79aceca5 bellard
    opc_handler_t **table, *handler;
8168 0fa85d43 bellard
    target_ulong pc_start;
8169 79aceca5 bellard
    uint16_t *gen_opc_end;
8170 a1d1bb31 aliguori
    CPUBreakpoint *bp;
8171 79aceca5 bellard
    int j, lj = -1;
8172 2e70f6ef pbrook
    int num_insns;
8173 2e70f6ef pbrook
    int max_insns;
8174 79aceca5 bellard
8175 79aceca5 bellard
    pc_start = tb->pc;
8176 79aceca5 bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8177 046d6672 bellard
    ctx.nip = pc_start;
8178 79aceca5 bellard
    ctx.tb = tb;
8179 e1833e1f j_mayer
    ctx.exception = POWERPC_EXCP_NONE;
8180 3fc6c082 bellard
    ctx.spr_cb = env->spr_cb;
8181 76db3ba4 aurel32
    ctx.mem_idx = env->mmu_idx;
8182 76db3ba4 aurel32
    ctx.access_type = -1;
8183 76db3ba4 aurel32
    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
8184 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
8185 d9bce9d9 j_mayer
    ctx.sf_mode = msr_sf;
8186 9a64fbe4 bellard
#endif
8187 3cc62370 bellard
    ctx.fpu_enabled = msr_fp;
8188 a9d9eb8f j_mayer
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
8189 d26bfc9a j_mayer
        ctx.spe_enabled = msr_spe;
8190 d26bfc9a j_mayer
    else
8191 d26bfc9a j_mayer
        ctx.spe_enabled = 0;
8192 a9d9eb8f j_mayer
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
8193 a9d9eb8f j_mayer
        ctx.altivec_enabled = msr_vr;
8194 a9d9eb8f j_mayer
    else
8195 a9d9eb8f j_mayer
        ctx.altivec_enabled = 0;
8196 d26bfc9a j_mayer
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8197 8cbcb4fa aurel32
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
8198 d26bfc9a j_mayer
    else
8199 8cbcb4fa aurel32
        ctx.singlestep_enabled = 0;
8200 d26bfc9a j_mayer
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8201 8cbcb4fa aurel32
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
8202 8cbcb4fa aurel32
    if (unlikely(env->singlestep_enabled))
8203 8cbcb4fa aurel32
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
8204 3fc6c082 bellard
#if defined (DO_SINGLE_STEP) && 0
8205 9a64fbe4 bellard
    /* Single step trace mode */
8206 9a64fbe4 bellard
    msr_se = 1;
8207 9a64fbe4 bellard
#endif
8208 2e70f6ef pbrook
    num_insns = 0;
8209 2e70f6ef pbrook
    max_insns = tb->cflags & CF_COUNT_MASK;
8210 2e70f6ef pbrook
    if (max_insns == 0)
8211 2e70f6ef pbrook
        max_insns = CF_COUNT_MASK;
8212 2e70f6ef pbrook
8213 2e70f6ef pbrook
    gen_icount_start();
8214 9a64fbe4 bellard
    /* Set env in case of segfault during code fetch */
8215 e1833e1f j_mayer
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
8216 c0ce998e aliguori
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8217 c0ce998e aliguori
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8218 a1d1bb31 aliguori
                if (bp->pc == ctx.nip) {
8219 e06fcd75 aurel32
                    gen_debug_exception(ctxp);
8220 ea4e754f bellard
                    break;
8221 ea4e754f bellard
                }
8222 ea4e754f bellard
            }
8223 ea4e754f bellard
        }
8224 76a66253 j_mayer
        if (unlikely(search_pc)) {
8225 79aceca5 bellard
            j = gen_opc_ptr - gen_opc_buf;
8226 79aceca5 bellard
            if (lj < j) {
8227 79aceca5 bellard
                lj++;
8228 79aceca5 bellard
                while (lj < j)
8229 79aceca5 bellard
                    gen_opc_instr_start[lj++] = 0;
8230 046d6672 bellard
                gen_opc_pc[lj] = ctx.nip;
8231 79aceca5 bellard
                gen_opc_instr_start[lj] = 1;
8232 2e70f6ef pbrook
                gen_opc_icount[lj] = num_insns;
8233 79aceca5 bellard
            }
8234 79aceca5 bellard
        }
8235 9fddaa0c bellard
#if defined PPC_DEBUG_DISAS
8236 9fddaa0c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
8237 79aceca5 bellard
            fprintf(logfile, "----------------\n");
8238 1b9eb036 j_mayer
            fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
8239 76db3ba4 aurel32
                    ctx.nip, ctx.mem_idx, (int)msr_ir);
8240 9a64fbe4 bellard
        }
8241 9a64fbe4 bellard
#endif
8242 2e70f6ef pbrook
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8243 2e70f6ef pbrook
            gen_io_start();
8244 76db3ba4 aurel32
        if (unlikely(ctx.le_mode)) {
8245 056401ea j_mayer
            ctx.opcode = bswap32(ldl_code(ctx.nip));
8246 056401ea j_mayer
        } else {
8247 056401ea j_mayer
            ctx.opcode = ldl_code(ctx.nip);
8248 111bfab3 bellard
        }
8249 9fddaa0c bellard
#if defined PPC_DEBUG_DISAS
8250 9fddaa0c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
8251 111bfab3 bellard
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
8252 9a64fbe4 bellard
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
8253 056401ea j_mayer
                    opc3(ctx.opcode), little_endian ? "little" : "big");
8254 79aceca5 bellard
        }
8255 79aceca5 bellard
#endif
8256 046d6672 bellard
        ctx.nip += 4;
8257 3fc6c082 bellard
        table = env->opcodes;
8258 2e70f6ef pbrook
        num_insns++;
8259 79aceca5 bellard
        handler = table[opc1(ctx.opcode)];
8260 79aceca5 bellard
        if (is_indirect_opcode(handler)) {
8261 79aceca5 bellard
            table = ind_table(handler);
8262 79aceca5 bellard
            handler = table[opc2(ctx.opcode)];
8263 79aceca5 bellard
            if (is_indirect_opcode(handler)) {
8264 79aceca5 bellard
                table = ind_table(handler);
8265 79aceca5 bellard
                handler = table[opc3(ctx.opcode)];
8266 79aceca5 bellard
            }
8267 79aceca5 bellard
        }
8268 79aceca5 bellard
        /* Is opcode *REALLY* valid ? */
8269 76a66253 j_mayer
        if (unlikely(handler->handler == &gen_invalid)) {
8270 4a057712 j_mayer
            if (loglevel != 0) {
8271 76a66253 j_mayer
                fprintf(logfile, "invalid/unsupported opcode: "
8272 6b542af7 j_mayer
                        "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
8273 76a66253 j_mayer
                        opc1(ctx.opcode), opc2(ctx.opcode),
8274 0411a972 j_mayer
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
8275 4b3686fa bellard
            } else {
8276 4b3686fa bellard
                printf("invalid/unsupported opcode: "
8277 6b542af7 j_mayer
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
8278 4b3686fa bellard
                       opc1(ctx.opcode), opc2(ctx.opcode),
8279 0411a972 j_mayer
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
8280 4b3686fa bellard
            }
8281 76a66253 j_mayer
        } else {
8282 76a66253 j_mayer
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
8283 4a057712 j_mayer
                if (loglevel != 0) {
8284 79aceca5 bellard
                    fprintf(logfile, "invalid bits: %08x for opcode: "
8285 6b542af7 j_mayer
                            "%02x - %02x - %02x (%08x) " ADDRX "\n",
8286 79aceca5 bellard
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
8287 79aceca5 bellard
                            opc2(ctx.opcode), opc3(ctx.opcode),
8288 046d6672 bellard
                            ctx.opcode, ctx.nip - 4);
8289 9a64fbe4 bellard
                } else {
8290 9a64fbe4 bellard
                    printf("invalid bits: %08x for opcode: "
8291 6b542af7 j_mayer
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
8292 76a66253 j_mayer
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
8293 76a66253 j_mayer
                           opc2(ctx.opcode), opc3(ctx.opcode),
8294 046d6672 bellard
                           ctx.opcode, ctx.nip - 4);
8295 76a66253 j_mayer
                }
8296 e06fcd75 aurel32
                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
8297 4b3686fa bellard
                break;
8298 79aceca5 bellard
            }
8299 79aceca5 bellard
        }
8300 4b3686fa bellard
        (*(handler->handler))(&ctx);
8301 76a66253 j_mayer
#if defined(DO_PPC_STATISTICS)
8302 76a66253 j_mayer
        handler->count++;
8303 76a66253 j_mayer
#endif
8304 9a64fbe4 bellard
        /* Check trace mode exceptions */
8305 8cbcb4fa aurel32
        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
8306 8cbcb4fa aurel32
                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
8307 8cbcb4fa aurel32
                     ctx.exception != POWERPC_SYSCALL &&
8308 8cbcb4fa aurel32
                     ctx.exception != POWERPC_EXCP_TRAP &&
8309 8cbcb4fa aurel32
                     ctx.exception != POWERPC_EXCP_BRANCH)) {
8310 e06fcd75 aurel32
            gen_exception(ctxp, POWERPC_EXCP_TRACE);
8311 d26bfc9a j_mayer
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
8312 2e70f6ef pbrook
                            (env->singlestep_enabled) ||
8313 2e70f6ef pbrook
                            num_insns >= max_insns)) {
8314 d26bfc9a j_mayer
            /* if we reach a page boundary or are single stepping, stop
8315 d26bfc9a j_mayer
             * generation
8316 d26bfc9a j_mayer
             */
8317 8dd4983c bellard
            break;
8318 76a66253 j_mayer
        }
8319 3fc6c082 bellard
#if defined (DO_SINGLE_STEP)
8320 3fc6c082 bellard
        break;
8321 3fc6c082 bellard
#endif
8322 3fc6c082 bellard
    }
8323 2e70f6ef pbrook
    if (tb->cflags & CF_LAST_IO)
8324 2e70f6ef pbrook
        gen_io_end();
8325 e1833e1f j_mayer
    if (ctx.exception == POWERPC_EXCP_NONE) {
8326 c1942362 bellard
        gen_goto_tb(&ctx, 0, ctx.nip);
8327 e1833e1f j_mayer
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
8328 8cbcb4fa aurel32
        if (unlikely(env->singlestep_enabled)) {
8329 e06fcd75 aurel32
            gen_debug_exception(ctxp);
8330 8cbcb4fa aurel32
        }
8331 76a66253 j_mayer
        /* Generate the return instruction */
8332 57fec1fe bellard
        tcg_gen_exit_tb(0);
8333 9a64fbe4 bellard
    }
8334 2e70f6ef pbrook
    gen_icount_end(tb, num_insns);
8335 79aceca5 bellard
    *gen_opc_ptr = INDEX_op_end;
8336 76a66253 j_mayer
    if (unlikely(search_pc)) {
8337 9a64fbe4 bellard
        j = gen_opc_ptr - gen_opc_buf;
8338 9a64fbe4 bellard
        lj++;
8339 9a64fbe4 bellard
        while (lj <= j)
8340 9a64fbe4 bellard
            gen_opc_instr_start[lj++] = 0;
8341 9a64fbe4 bellard
    } else {
8342 046d6672 bellard
        tb->size = ctx.nip - pc_start;
8343 2e70f6ef pbrook
        tb->icount = num_insns;
8344 9a64fbe4 bellard
    }
8345 d9bce9d9 j_mayer
#if defined(DEBUG_DISAS)
8346 9fddaa0c bellard
    if (loglevel & CPU_LOG_TB_CPU) {
8347 9a64fbe4 bellard
        fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
8348 7fe48483 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
8349 9fddaa0c bellard
    }
8350 9fddaa0c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
8351 76a66253 j_mayer
        int flags;
8352 237c0af0 j_mayer
        flags = env->bfd_mach;
8353 76db3ba4 aurel32
        flags |= ctx.le_mode << 16;
8354 0fa85d43 bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
8355 76a66253 j_mayer
        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
8356 79aceca5 bellard
        fprintf(logfile, "\n");
8357 9fddaa0c bellard
    }
8358 79aceca5 bellard
#endif
8359 79aceca5 bellard
}
8360 79aceca5 bellard
8361 2cfc5f17 ths
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8362 79aceca5 bellard
{
8363 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 0);
8364 79aceca5 bellard
}
8365 79aceca5 bellard
8366 2cfc5f17 ths
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8367 79aceca5 bellard
{
8368 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 1);
8369 79aceca5 bellard
}
8370 d2856f1a aurel32
8371 d2856f1a aurel32
void gen_pc_load(CPUState *env, TranslationBlock *tb,
8372 d2856f1a aurel32
                unsigned long searched_pc, int pc_pos, void *puc)
8373 d2856f1a aurel32
{
8374 d2856f1a aurel32
    env->nip = gen_opc_pc[pc_pos];
8375 d2856f1a aurel32
}