Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ 7487953d

History | View | Annotate | Download (283.1 kB)

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

6976 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
6977 0487d6a8 j_mayer
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
6978 0487d6a8 j_mayer
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
6979 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
6980 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
6981 0487d6a8 j_mayer
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
6982 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
6983 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
6984 0487d6a8 j_mayer
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
6985 0487d6a8 j_mayer
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
6986 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
6987 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
6988 0487d6a8 j_mayer
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
6989 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
6990 0487d6a8 j_mayer

6991 0487d6a8 j_mayer
GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
6992 0487d6a8 j_mayer
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
6993 0487d6a8 j_mayer
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
6994 0487d6a8 j_mayer
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
6995 0487d6a8 j_mayer
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
6996 0487d6a8 j_mayer
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
6997 0487d6a8 j_mayer

6998 0487d6a8 j_mayer
GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
6999 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
7000 0487d6a8 j_mayer
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
7001 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
7002 0487d6a8 j_mayer
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
7003 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
7004 0487d6a8 j_mayer
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
7005 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
7006 0487d6a8 j_mayer
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
7007 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
7008 0487d6a8 j_mayer
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
7009 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
7010 0487d6a8 j_mayer

7011 0487d6a8 j_mayer
GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
7012 0487d6a8 j_mayer
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
7013 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
7014 0487d6a8 j_mayer
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
7015 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
7016 0487d6a8 j_mayer

7017 0487d6a8 j_mayer
GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
7018 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
7019 0487d6a8 j_mayer
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
7020 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
7021 0487d6a8 j_mayer
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
7022 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
7023 0487d6a8 j_mayer
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
7024 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
7025 0487d6a8 j_mayer
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
7026 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
7027 0487d6a8 j_mayer
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
7028 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
7029 0487d6a8 j_mayer

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