Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ 604457d7

History | View | Annotate | Download (307.8 kB)

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

7540 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
7541 0487d6a8 j_mayer
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
7542 0487d6a8 j_mayer
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
7543 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
7544 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
7545 0487d6a8 j_mayer
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
7546 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
7547 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
7548 0487d6a8 j_mayer
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
7549 0487d6a8 j_mayer
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
7550 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
7551 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
7552 0487d6a8 j_mayer
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
7553 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
7554 0487d6a8 j_mayer

7555 0487d6a8 j_mayer
GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
7556 0487d6a8 j_mayer
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
7557 0487d6a8 j_mayer
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
7558 0487d6a8 j_mayer
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
7559 0487d6a8 j_mayer
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
7560 0487d6a8 j_mayer
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
7561 0487d6a8 j_mayer

7562 0487d6a8 j_mayer
GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
7563 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
7564 0487d6a8 j_mayer
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
7565 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
7566 0487d6a8 j_mayer
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
7567 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
7568 0487d6a8 j_mayer
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
7569 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
7570 0487d6a8 j_mayer
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
7571 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
7572 0487d6a8 j_mayer
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
7573 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
7574 0487d6a8 j_mayer

7575 0487d6a8 j_mayer
GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
7576 0487d6a8 j_mayer
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
7577 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
7578 0487d6a8 j_mayer
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
7579 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
7580 0487d6a8 j_mayer

7581 0487d6a8 j_mayer
GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
7582 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
7583 0487d6a8 j_mayer
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
7584 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
7585 0487d6a8 j_mayer
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
7586 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
7587 0487d6a8 j_mayer
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
7588 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
7589 0487d6a8 j_mayer
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
7590 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
7591 0487d6a8 j_mayer
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
7592 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
7593 0487d6a8 j_mayer

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