Statistics
| Branch: | Revision:

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

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

7547 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
7548 0487d6a8 j_mayer
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
7549 0487d6a8 j_mayer
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
7550 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
7551 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
7552 0487d6a8 j_mayer
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
7553 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
7554 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
7555 0487d6a8 j_mayer
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
7556 0487d6a8 j_mayer
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
7557 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
7558 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
7559 0487d6a8 j_mayer
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
7560 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
7561 0487d6a8 j_mayer

7562 0487d6a8 j_mayer
GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
7563 0487d6a8 j_mayer
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
7564 0487d6a8 j_mayer
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
7565 0487d6a8 j_mayer
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
7566 0487d6a8 j_mayer
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
7567 0487d6a8 j_mayer
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
7568 0487d6a8 j_mayer

7569 0487d6a8 j_mayer
GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
7570 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
7571 0487d6a8 j_mayer
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
7572 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
7573 0487d6a8 j_mayer
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
7574 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
7575 0487d6a8 j_mayer
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
7576 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
7577 0487d6a8 j_mayer
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
7578 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
7579 0487d6a8 j_mayer
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
7580 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
7581 0487d6a8 j_mayer

7582 0487d6a8 j_mayer
GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
7583 0487d6a8 j_mayer
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
7584 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
7585 0487d6a8 j_mayer
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
7586 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
7587 0487d6a8 j_mayer

7588 0487d6a8 j_mayer
GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
7589 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
7590 0487d6a8 j_mayer
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
7591 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
7592 0487d6a8 j_mayer
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
7593 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
7594 0487d6a8 j_mayer
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
7595 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
7596 0487d6a8 j_mayer
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
7597 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
7598 0487d6a8 j_mayer
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
7599 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
7600 0487d6a8 j_mayer

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