Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ a1d1bb31

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

6794 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
6795 0487d6a8 j_mayer
GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
6796 0487d6a8 j_mayer
GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
6797 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
6798 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
6799 0487d6a8 j_mayer
GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
6800 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
6801 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
6802 0487d6a8 j_mayer
GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
6803 0487d6a8 j_mayer
GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
6804 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
6805 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
6806 0487d6a8 j_mayer
GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
6807 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
6808 0487d6a8 j_mayer

6809 0487d6a8 j_mayer
GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
6810 0487d6a8 j_mayer
GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
6811 0487d6a8 j_mayer
GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
6812 0487d6a8 j_mayer
GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
6813 0487d6a8 j_mayer
GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
6814 0487d6a8 j_mayer
GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
6815 0487d6a8 j_mayer

6816 0487d6a8 j_mayer
GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
6817 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
6818 0487d6a8 j_mayer
GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
6819 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
6820 0487d6a8 j_mayer
GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
6821 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
6822 0487d6a8 j_mayer
GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
6823 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
6824 0487d6a8 j_mayer
GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
6825 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
6826 0487d6a8 j_mayer
GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
6827 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
6828 0487d6a8 j_mayer

6829 0487d6a8 j_mayer
GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
6830 0487d6a8 j_mayer
GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
6831 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
6832 0487d6a8 j_mayer
GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
6833 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
6834 0487d6a8 j_mayer

6835 0487d6a8 j_mayer
GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
6836 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
6837 0487d6a8 j_mayer
GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
6838 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
6839 0487d6a8 j_mayer
GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
6840 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
6841 0487d6a8 j_mayer
GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
6842 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
6843 0487d6a8 j_mayer
GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
6844 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
6845 0487d6a8 j_mayer
GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
6846 0487d6a8 j_mayer
GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
6847 0487d6a8 j_mayer

6848 0487d6a8 j_mayer
GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, PPC_SPE);
6849 0487d6a8 j_mayer
GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, PPC_SPE);
6850 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0x00000000, PPC_SPE);
6851 0487d6a8 j_mayer
GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, PPC_SPE);
6852 0487d6a8 j_mayer
GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0x00000000, PPC_SPE);
6853 0487d6a8 j_mayer
#endif
6854 0487d6a8 j_mayer
6855 0487d6a8 j_mayer
/***                      SPE floating-point extension                     ***/
6856 0487d6a8 j_mayer
#define GEN_SPEFPUOP_CONV(name)                                               \
6857 b068d6a7 j_mayer
static always_inline void gen_##name (DisasContext *ctx)                      \
6858 0487d6a8 j_mayer
{                                                                             \
6859 f78fb44e aurel32
    gen_load_gpr64(cpu_T64[0], rB(ctx->opcode));                              \
6860 0487d6a8 j_mayer
    gen_op_##name();                                                          \
6861 f78fb44e aurel32
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6862 0487d6a8 j_mayer
}
6863 0487d6a8 j_mayer
6864 57951c27 aurel32
#define GEN_SPEFPUOP_ARITH1(name)                                             \
6865 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6866 57951c27 aurel32
{                                                                             \
6867 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6868 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6869 57951c27 aurel32
        return;                                                               \
6870 57951c27 aurel32
    }                                                                         \
6871 57951c27 aurel32
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
6872 57951c27 aurel32
    gen_op_##name();                                                          \
6873 57951c27 aurel32
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6874 57951c27 aurel32
}
6875 57951c27 aurel32
6876 57951c27 aurel32
#define GEN_SPEFPUOP_ARITH2(name)                                             \
6877 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6878 57951c27 aurel32
{                                                                             \
6879 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6880 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6881 57951c27 aurel32
        return;                                                               \
6882 57951c27 aurel32
    }                                                                         \
6883 57951c27 aurel32
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
6884 57951c27 aurel32
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
6885 57951c27 aurel32
    gen_op_##name();                                                          \
6886 57951c27 aurel32
    gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);                             \
6887 57951c27 aurel32
}
6888 57951c27 aurel32
6889 57951c27 aurel32
#define GEN_SPEFPUOP_COMP(name)                                               \
6890 57951c27 aurel32
static always_inline void gen_##name (DisasContext *ctx)                      \
6891 57951c27 aurel32
{                                                                             \
6892 a7812ae4 pbrook
    TCGv_i32 crf = cpu_crf[crfD(ctx->opcode)];                                \
6893 57951c27 aurel32
    if (unlikely(!ctx->spe_enabled)) {                                        \
6894 57951c27 aurel32
        GEN_EXCP_NO_AP(ctx);                                                  \
6895 57951c27 aurel32
        return;                                                               \
6896 57951c27 aurel32
    }                                                                         \
6897 57951c27 aurel32
    gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));                              \
6898 57951c27 aurel32
    gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));                              \
6899 57951c27 aurel32
    gen_op_##name();                                                          \
6900 a7812ae4 pbrook
    tcg_gen_trunc_tl_i32(crf, cpu_T[0]);                                      \
6901 a7812ae4 pbrook
    tcg_gen_andi_i32(crf, crf, 0xf);                                          \
6902 57951c27 aurel32
}
6903 57951c27 aurel32
6904 0487d6a8 j_mayer
/* Single precision floating-point vectors operations */
6905 0487d6a8 j_mayer
/* Arithmetic */
6906 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(evfsadd);
6907 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(evfssub);
6908 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(evfsmul);
6909 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(evfsdiv);
6910 57951c27 aurel32
GEN_SPEFPUOP_ARITH1(evfsabs);
6911 57951c27 aurel32
GEN_SPEFPUOP_ARITH1(evfsnabs);
6912 57951c27 aurel32
GEN_SPEFPUOP_ARITH1(evfsneg);
6913 0487d6a8 j_mayer
/* Conversion */
6914 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfscfui);
6915 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfscfsi);
6916 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfscfuf);
6917 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfscfsf);
6918 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfsctui);
6919 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfsctsi);
6920 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfsctuf);
6921 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfsctsf);
6922 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfsctuiz);
6923 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(evfsctsiz);
6924 0487d6a8 j_mayer
/* Comparison */
6925 57951c27 aurel32
GEN_SPEFPUOP_COMP(evfscmpgt);
6926 57951c27 aurel32
GEN_SPEFPUOP_COMP(evfscmplt);
6927 57951c27 aurel32
GEN_SPEFPUOP_COMP(evfscmpeq);
6928 57951c27 aurel32
GEN_SPEFPUOP_COMP(evfststgt);
6929 57951c27 aurel32
GEN_SPEFPUOP_COMP(evfststlt);
6930 57951c27 aurel32
GEN_SPEFPUOP_COMP(evfststeq);
6931 0487d6a8 j_mayer
6932 0487d6a8 j_mayer
/* Opcodes definitions */
6933 0487d6a8 j_mayer
GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
6934 0487d6a8 j_mayer
GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
6935 0487d6a8 j_mayer
GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
6936 0487d6a8 j_mayer
GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
6937 0487d6a8 j_mayer
GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
6938 0487d6a8 j_mayer
GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
6939 0487d6a8 j_mayer
GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
6940 0487d6a8 j_mayer
GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
6941 0487d6a8 j_mayer
GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
6942 0487d6a8 j_mayer
GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
6943 0487d6a8 j_mayer
GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
6944 0487d6a8 j_mayer
GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
6945 0487d6a8 j_mayer
GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
6946 0487d6a8 j_mayer
GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
6947 0487d6a8 j_mayer
6948 0487d6a8 j_mayer
/* Single precision floating-point operations */
6949 0487d6a8 j_mayer
/* Arithmetic */
6950 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(efsadd);
6951 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(efssub);
6952 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(efsmul);
6953 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(efsdiv);
6954 57951c27 aurel32
GEN_SPEFPUOP_ARITH1(efsabs);
6955 57951c27 aurel32
GEN_SPEFPUOP_ARITH1(efsnabs);
6956 57951c27 aurel32
GEN_SPEFPUOP_ARITH1(efsneg);
6957 0487d6a8 j_mayer
/* Conversion */
6958 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efscfui);
6959 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efscfsi);
6960 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efscfuf);
6961 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efscfsf);
6962 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efsctui);
6963 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efsctsi);
6964 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efsctuf);
6965 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efsctsf);
6966 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efsctuiz);
6967 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efsctsiz);
6968 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efscfd);
6969 0487d6a8 j_mayer
/* Comparison */
6970 57951c27 aurel32
GEN_SPEFPUOP_COMP(efscmpgt);
6971 57951c27 aurel32
GEN_SPEFPUOP_COMP(efscmplt);
6972 57951c27 aurel32
GEN_SPEFPUOP_COMP(efscmpeq);
6973 57951c27 aurel32
GEN_SPEFPUOP_COMP(efststgt);
6974 57951c27 aurel32
GEN_SPEFPUOP_COMP(efststlt);
6975 57951c27 aurel32
GEN_SPEFPUOP_COMP(efststeq);
6976 0487d6a8 j_mayer
6977 0487d6a8 j_mayer
/* Opcodes definitions */
6978 05332d70 j_mayer
GEN_SPE(efsadd,         efssub,        0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
6979 0487d6a8 j_mayer
GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
6980 0487d6a8 j_mayer
GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
6981 0487d6a8 j_mayer
GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
6982 0487d6a8 j_mayer
GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
6983 0487d6a8 j_mayer
GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
6984 0487d6a8 j_mayer
GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
6985 0487d6a8 j_mayer
GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
6986 0487d6a8 j_mayer
GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
6987 0487d6a8 j_mayer
GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
6988 9ceb2a77 ths
GEN_SPE(efsctuiz,       speundef,      0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
6989 9ceb2a77 ths
GEN_SPE(efsctsiz,       speundef,      0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
6990 0487d6a8 j_mayer
GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
6991 0487d6a8 j_mayer
GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
6992 0487d6a8 j_mayer
6993 0487d6a8 j_mayer
/* Double precision floating-point operations */
6994 0487d6a8 j_mayer
/* Arithmetic */
6995 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(efdadd);
6996 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(efdsub);
6997 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(efdmul);
6998 57951c27 aurel32
GEN_SPEFPUOP_ARITH2(efddiv);
6999 57951c27 aurel32
GEN_SPEFPUOP_ARITH1(efdabs);
7000 57951c27 aurel32
GEN_SPEFPUOP_ARITH1(efdnabs);
7001 57951c27 aurel32
GEN_SPEFPUOP_ARITH1(efdneg);
7002 0487d6a8 j_mayer
/* Conversion */
7003 0487d6a8 j_mayer
7004 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdcfui);
7005 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdcfsi);
7006 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdcfuf);
7007 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdcfsf);
7008 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdctui);
7009 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdctsi);
7010 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdctuf);
7011 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdctsf);
7012 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdctuiz);
7013 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdctsiz);
7014 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdcfs);
7015 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdcfuid);
7016 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdcfsid);
7017 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdctuidz);
7018 0487d6a8 j_mayer
GEN_SPEFPUOP_CONV(efdctsidz);
7019 0487d6a8 j_mayer
/* Comparison */
7020 57951c27 aurel32
GEN_SPEFPUOP_COMP(efdcmpgt);
7021 57951c27 aurel32
GEN_SPEFPUOP_COMP(efdcmplt);
7022 57951c27 aurel32
GEN_SPEFPUOP_COMP(efdcmpeq);
7023 57951c27 aurel32
GEN_SPEFPUOP_COMP(efdtstgt);
7024 57951c27 aurel32
GEN_SPEFPUOP_COMP(efdtstlt);
7025 57951c27 aurel32
GEN_SPEFPUOP_COMP(efdtsteq);
7026 0487d6a8 j_mayer
7027 0487d6a8 j_mayer
/* Opcodes definitions */
7028 0487d6a8 j_mayer
GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
7029 0487d6a8 j_mayer
GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
7030 0487d6a8 j_mayer
GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
7031 0487d6a8 j_mayer
GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
7032 0487d6a8 j_mayer
GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
7033 0487d6a8 j_mayer
GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
7034 0487d6a8 j_mayer
GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
7035 0487d6a8 j_mayer
GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
7036 0487d6a8 j_mayer
GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
7037 0487d6a8 j_mayer
GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
7038 0487d6a8 j_mayer
GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
7039 0487d6a8 j_mayer
GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
7040 0487d6a8 j_mayer
GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
7041 0487d6a8 j_mayer
GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
7042 0487d6a8 j_mayer
GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
7043 0487d6a8 j_mayer
GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
7044 0487d6a8 j_mayer
7045 79aceca5 bellard
/* End opcode list */
7046 79aceca5 bellard
GEN_OPCODE_MARK(end);
7047 79aceca5 bellard
7048 3fc6c082 bellard
#include "translate_init.c"
7049 0411a972 j_mayer
#include "helper_regs.h"
7050 79aceca5 bellard
7051 9a64fbe4 bellard
/*****************************************************************************/
7052 3fc6c082 bellard
/* Misc PowerPC helpers */
7053 36081602 j_mayer
void cpu_dump_state (CPUState *env, FILE *f,
7054 36081602 j_mayer
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7055 36081602 j_mayer
                     int flags)
7056 79aceca5 bellard
{
7057 3fc6c082 bellard
#define RGPL  4
7058 3fc6c082 bellard
#define RFPL  4
7059 3fc6c082 bellard
7060 79aceca5 bellard
    int i;
7061 79aceca5 bellard
7062 077fc206 j_mayer
    cpu_fprintf(f, "NIP " ADDRX "   LR " ADDRX " CTR " ADDRX " XER %08x\n",
7063 3d7b417e aurel32
                env->nip, env->lr, env->ctr, env->xer);
7064 6b542af7 j_mayer
    cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX "  HF " ADDRX " idx %d\n",
7065 6b542af7 j_mayer
                env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
7066 d9bce9d9 j_mayer
#if !defined(NO_TIMER_DUMP)
7067 077fc206 j_mayer
    cpu_fprintf(f, "TB %08x %08x "
7068 76a66253 j_mayer
#if !defined(CONFIG_USER_ONLY)
7069 76a66253 j_mayer
                "DECR %08x"
7070 76a66253 j_mayer
#endif
7071 76a66253 j_mayer
                "\n",
7072 077fc206 j_mayer
                cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
7073 76a66253 j_mayer
#if !defined(CONFIG_USER_ONLY)
7074 76a66253 j_mayer
                , cpu_ppc_load_decr(env)
7075 76a66253 j_mayer
#endif
7076 76a66253 j_mayer
                );
7077 077fc206 j_mayer
#endif
7078 76a66253 j_mayer
    for (i = 0; i < 32; i++) {
7079 3fc6c082 bellard
        if ((i & (RGPL - 1)) == 0)
7080 3fc6c082 bellard
            cpu_fprintf(f, "GPR%02d", i);
7081 6b542af7 j_mayer
        cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
7082 3fc6c082 bellard
        if ((i & (RGPL - 1)) == (RGPL - 1))
7083 7fe48483 bellard
            cpu_fprintf(f, "\n");
7084 76a66253 j_mayer
    }
7085 3fc6c082 bellard
    cpu_fprintf(f, "CR ");
7086 76a66253 j_mayer
    for (i = 0; i < 8; i++)
7087 7fe48483 bellard
        cpu_fprintf(f, "%01x", env->crf[i]);
7088 7fe48483 bellard
    cpu_fprintf(f, "  [");
7089 76a66253 j_mayer
    for (i = 0; i < 8; i++) {
7090 76a66253 j_mayer
        char a = '-';
7091 76a66253 j_mayer
        if (env->crf[i] & 0x08)
7092 76a66253 j_mayer
            a = 'L';
7093 76a66253 j_mayer
        else if (env->crf[i] & 0x04)
7094 76a66253 j_mayer
            a = 'G';
7095 76a66253 j_mayer
        else if (env->crf[i] & 0x02)
7096 76a66253 j_mayer
            a = 'E';
7097 7fe48483 bellard
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
7098 76a66253 j_mayer
    }
7099 6b542af7 j_mayer
    cpu_fprintf(f, " ]             RES " ADDRX "\n", env->reserve);
7100 3fc6c082 bellard
    for (i = 0; i < 32; i++) {
7101 3fc6c082 bellard
        if ((i & (RFPL - 1)) == 0)
7102 3fc6c082 bellard
            cpu_fprintf(f, "FPR%02d", i);
7103 26a76461 bellard
        cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
7104 3fc6c082 bellard
        if ((i & (RFPL - 1)) == (RFPL - 1))
7105 7fe48483 bellard
            cpu_fprintf(f, "\n");
7106 79aceca5 bellard
    }
7107 f2e63a42 j_mayer
#if !defined(CONFIG_USER_ONLY)
7108 6b542af7 j_mayer
    cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
7109 3fc6c082 bellard
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
7110 f2e63a42 j_mayer
#endif
7111 79aceca5 bellard
7112 3fc6c082 bellard
#undef RGPL
7113 3fc6c082 bellard
#undef RFPL
7114 79aceca5 bellard
}
7115 79aceca5 bellard
7116 76a66253 j_mayer
void cpu_dump_statistics (CPUState *env, FILE*f,
7117 76a66253 j_mayer
                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7118 76a66253 j_mayer
                          int flags)
7119 76a66253 j_mayer
{
7120 76a66253 j_mayer
#if defined(DO_PPC_STATISTICS)
7121 76a66253 j_mayer
    opc_handler_t **t1, **t2, **t3, *handler;
7122 76a66253 j_mayer
    int op1, op2, op3;
7123 76a66253 j_mayer
7124 76a66253 j_mayer
    t1 = env->opcodes;
7125 76a66253 j_mayer
    for (op1 = 0; op1 < 64; op1++) {
7126 76a66253 j_mayer
        handler = t1[op1];
7127 76a66253 j_mayer
        if (is_indirect_opcode(handler)) {
7128 76a66253 j_mayer
            t2 = ind_table(handler);
7129 76a66253 j_mayer
            for (op2 = 0; op2 < 32; op2++) {
7130 76a66253 j_mayer
                handler = t2[op2];
7131 76a66253 j_mayer
                if (is_indirect_opcode(handler)) {
7132 76a66253 j_mayer
                    t3 = ind_table(handler);
7133 76a66253 j_mayer
                    for (op3 = 0; op3 < 32; op3++) {
7134 76a66253 j_mayer
                        handler = t3[op3];
7135 76a66253 j_mayer
                        if (handler->count == 0)
7136 76a66253 j_mayer
                            continue;
7137 76a66253 j_mayer
                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
7138 76a66253 j_mayer
                                    "%016llx %lld\n",
7139 76a66253 j_mayer
                                    op1, op2, op3, op1, (op3 << 5) | op2,
7140 76a66253 j_mayer
                                    handler->oname,
7141 76a66253 j_mayer
                                    handler->count, handler->count);
7142 76a66253 j_mayer
                    }
7143 76a66253 j_mayer
                } else {
7144 76a66253 j_mayer
                    if (handler->count == 0)
7145 76a66253 j_mayer
                        continue;
7146 76a66253 j_mayer
                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
7147 76a66253 j_mayer
                                "%016llx %lld\n",
7148 76a66253 j_mayer
                                op1, op2, op1, op2, handler->oname,
7149 76a66253 j_mayer
                                handler->count, handler->count);
7150 76a66253 j_mayer
                }
7151 76a66253 j_mayer
            }
7152 76a66253 j_mayer
        } else {
7153 76a66253 j_mayer
            if (handler->count == 0)
7154 76a66253 j_mayer
                continue;
7155 76a66253 j_mayer
            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016llx %lld\n",
7156 76a66253 j_mayer
                        op1, op1, handler->oname,
7157 76a66253 j_mayer
                        handler->count, handler->count);
7158 76a66253 j_mayer
        }
7159 76a66253 j_mayer
    }
7160 76a66253 j_mayer
#endif
7161 76a66253 j_mayer
}
7162 76a66253 j_mayer
7163 9a64fbe4 bellard
/*****************************************************************************/
7164 2cfc5f17 ths
static always_inline void gen_intermediate_code_internal (CPUState *env,
7165 2cfc5f17 ths
                                                          TranslationBlock *tb,
7166 2cfc5f17 ths
                                                          int search_pc)
7167 79aceca5 bellard
{
7168 9fddaa0c bellard
    DisasContext ctx, *ctxp = &ctx;
7169 79aceca5 bellard
    opc_handler_t **table, *handler;
7170 0fa85d43 bellard
    target_ulong pc_start;
7171 79aceca5 bellard
    uint16_t *gen_opc_end;
7172 056401ea j_mayer
    int supervisor, little_endian;
7173 a1d1bb31 aliguori
    CPUBreakpoint *bp;
7174 79aceca5 bellard
    int j, lj = -1;
7175 2e70f6ef pbrook
    int num_insns;
7176 2e70f6ef pbrook
    int max_insns;
7177 79aceca5 bellard
7178 79aceca5 bellard
    pc_start = tb->pc;
7179 79aceca5 bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7180 7c58044c j_mayer
#if defined(OPTIMIZE_FPRF_UPDATE)
7181 7c58044c j_mayer
    gen_fprf_ptr = gen_fprf_buf;
7182 7c58044c j_mayer
#endif
7183 046d6672 bellard
    ctx.nip = pc_start;
7184 79aceca5 bellard
    ctx.tb = tb;
7185 e1833e1f j_mayer
    ctx.exception = POWERPC_EXCP_NONE;
7186 3fc6c082 bellard
    ctx.spr_cb = env->spr_cb;
7187 6ebbf390 j_mayer
    supervisor = env->mmu_idx;
7188 6ebbf390 j_mayer
#if !defined(CONFIG_USER_ONLY)
7189 2857068e j_mayer
    ctx.supervisor = supervisor;
7190 d9bce9d9 j_mayer
#endif
7191 056401ea j_mayer
    little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
7192 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
7193 d9bce9d9 j_mayer
    ctx.sf_mode = msr_sf;
7194 056401ea j_mayer
    ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
7195 2857068e j_mayer
#else
7196 056401ea j_mayer
    ctx.mem_idx = (supervisor << 1) | little_endian;
7197 9a64fbe4 bellard
#endif
7198 d63001d1 j_mayer
    ctx.dcache_line_size = env->dcache_line_size;
7199 3cc62370 bellard
    ctx.fpu_enabled = msr_fp;
7200 a9d9eb8f j_mayer
    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
7201 d26bfc9a j_mayer
        ctx.spe_enabled = msr_spe;
7202 d26bfc9a j_mayer
    else
7203 d26bfc9a j_mayer
        ctx.spe_enabled = 0;
7204 a9d9eb8f j_mayer
    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
7205 a9d9eb8f j_mayer
        ctx.altivec_enabled = msr_vr;
7206 a9d9eb8f j_mayer
    else
7207 a9d9eb8f j_mayer
        ctx.altivec_enabled = 0;
7208 d26bfc9a j_mayer
    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
7209 8cbcb4fa aurel32
        ctx.singlestep_enabled = CPU_SINGLE_STEP;
7210 d26bfc9a j_mayer
    else
7211 8cbcb4fa aurel32
        ctx.singlestep_enabled = 0;
7212 d26bfc9a j_mayer
    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
7213 8cbcb4fa aurel32
        ctx.singlestep_enabled |= CPU_BRANCH_STEP;
7214 8cbcb4fa aurel32
    if (unlikely(env->singlestep_enabled))
7215 8cbcb4fa aurel32
        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
7216 3fc6c082 bellard
#if defined (DO_SINGLE_STEP) && 0
7217 9a64fbe4 bellard
    /* Single step trace mode */
7218 9a64fbe4 bellard
    msr_se = 1;
7219 9a64fbe4 bellard
#endif
7220 2e70f6ef pbrook
    num_insns = 0;
7221 2e70f6ef pbrook
    max_insns = tb->cflags & CF_COUNT_MASK;
7222 2e70f6ef pbrook
    if (max_insns == 0)
7223 2e70f6ef pbrook
        max_insns = CF_COUNT_MASK;
7224 2e70f6ef pbrook
7225 2e70f6ef pbrook
    gen_icount_start();
7226 9a64fbe4 bellard
    /* Set env in case of segfault during code fetch */
7227 e1833e1f j_mayer
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
7228 a1d1bb31 aliguori
        if (unlikely(env->breakpoints)) {
7229 a1d1bb31 aliguori
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
7230 a1d1bb31 aliguori
                if (bp->pc == ctx.nip) {
7231 5fafdf24 ths
                    gen_update_nip(&ctx, ctx.nip);
7232 ea4e754f bellard
                    gen_op_debug();
7233 ea4e754f bellard
                    break;
7234 ea4e754f bellard
                }
7235 ea4e754f bellard
            }
7236 ea4e754f bellard
        }
7237 76a66253 j_mayer
        if (unlikely(search_pc)) {
7238 79aceca5 bellard
            j = gen_opc_ptr - gen_opc_buf;
7239 79aceca5 bellard
            if (lj < j) {
7240 79aceca5 bellard
                lj++;
7241 79aceca5 bellard
                while (lj < j)
7242 79aceca5 bellard
                    gen_opc_instr_start[lj++] = 0;
7243 046d6672 bellard
                gen_opc_pc[lj] = ctx.nip;
7244 79aceca5 bellard
                gen_opc_instr_start[lj] = 1;
7245 2e70f6ef pbrook
                gen_opc_icount[lj] = num_insns;
7246 79aceca5 bellard
            }
7247 79aceca5 bellard
        }
7248 9fddaa0c bellard
#if defined PPC_DEBUG_DISAS
7249 9fddaa0c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
7250 79aceca5 bellard
            fprintf(logfile, "----------------\n");
7251 1b9eb036 j_mayer
            fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
7252 0411a972 j_mayer
                    ctx.nip, supervisor, (int)msr_ir);
7253 9a64fbe4 bellard
        }
7254 9a64fbe4 bellard
#endif
7255 2e70f6ef pbrook
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
7256 2e70f6ef pbrook
            gen_io_start();
7257 056401ea j_mayer
        if (unlikely(little_endian)) {
7258 056401ea j_mayer
            ctx.opcode = bswap32(ldl_code(ctx.nip));
7259 056401ea j_mayer
        } else {
7260 056401ea j_mayer
            ctx.opcode = ldl_code(ctx.nip);
7261 111bfab3 bellard
        }
7262 9fddaa0c bellard
#if defined PPC_DEBUG_DISAS
7263 9fddaa0c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
7264 111bfab3 bellard
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
7265 9a64fbe4 bellard
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
7266 056401ea j_mayer
                    opc3(ctx.opcode), little_endian ? "little" : "big");
7267 79aceca5 bellard
        }
7268 79aceca5 bellard
#endif
7269 046d6672 bellard
        ctx.nip += 4;
7270 3fc6c082 bellard
        table = env->opcodes;
7271 2e70f6ef pbrook
        num_insns++;
7272 79aceca5 bellard
        handler = table[opc1(ctx.opcode)];
7273 79aceca5 bellard
        if (is_indirect_opcode(handler)) {
7274 79aceca5 bellard
            table = ind_table(handler);
7275 79aceca5 bellard
            handler = table[opc2(ctx.opcode)];
7276 79aceca5 bellard
            if (is_indirect_opcode(handler)) {
7277 79aceca5 bellard
                table = ind_table(handler);
7278 79aceca5 bellard
                handler = table[opc3(ctx.opcode)];
7279 79aceca5 bellard
            }
7280 79aceca5 bellard
        }
7281 79aceca5 bellard
        /* Is opcode *REALLY* valid ? */
7282 76a66253 j_mayer
        if (unlikely(handler->handler == &gen_invalid)) {
7283 4a057712 j_mayer
            if (loglevel != 0) {
7284 76a66253 j_mayer
                fprintf(logfile, "invalid/unsupported opcode: "
7285 6b542af7 j_mayer
                        "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
7286 76a66253 j_mayer
                        opc1(ctx.opcode), opc2(ctx.opcode),
7287 0411a972 j_mayer
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
7288 4b3686fa bellard
            } else {
7289 4b3686fa bellard
                printf("invalid/unsupported opcode: "
7290 6b542af7 j_mayer
                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
7291 4b3686fa bellard
                       opc1(ctx.opcode), opc2(ctx.opcode),
7292 0411a972 j_mayer
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
7293 4b3686fa bellard
            }
7294 76a66253 j_mayer
        } else {
7295 76a66253 j_mayer
            if (unlikely((ctx.opcode & handler->inval) != 0)) {
7296 4a057712 j_mayer
                if (loglevel != 0) {
7297 79aceca5 bellard
                    fprintf(logfile, "invalid bits: %08x for opcode: "
7298 6b542af7 j_mayer
                            "%02x - %02x - %02x (%08x) " ADDRX "\n",
7299 79aceca5 bellard
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
7300 79aceca5 bellard
                            opc2(ctx.opcode), opc3(ctx.opcode),
7301 046d6672 bellard
                            ctx.opcode, ctx.nip - 4);
7302 9a64fbe4 bellard
                } else {
7303 9a64fbe4 bellard
                    printf("invalid bits: %08x for opcode: "
7304 6b542af7 j_mayer
                           "%02x - %02x - %02x (%08x) " ADDRX "\n",
7305 76a66253 j_mayer
                           ctx.opcode & handler->inval, opc1(ctx.opcode),
7306 76a66253 j_mayer
                           opc2(ctx.opcode), opc3(ctx.opcode),
7307 046d6672 bellard
                           ctx.opcode, ctx.nip - 4);
7308 76a66253 j_mayer
                }
7309 e1833e1f j_mayer
                GEN_EXCP_INVAL(ctxp);
7310 4b3686fa bellard
                break;
7311 79aceca5 bellard
            }
7312 79aceca5 bellard
        }
7313 4b3686fa bellard
        (*(handler->handler))(&ctx);
7314 76a66253 j_mayer
#if defined(DO_PPC_STATISTICS)
7315 76a66253 j_mayer
        handler->count++;
7316 76a66253 j_mayer
#endif
7317 9a64fbe4 bellard
        /* Check trace mode exceptions */
7318 8cbcb4fa aurel32
        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
7319 8cbcb4fa aurel32
                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
7320 8cbcb4fa aurel32
                     ctx.exception != POWERPC_SYSCALL &&
7321 8cbcb4fa aurel32
                     ctx.exception != POWERPC_EXCP_TRAP &&
7322 8cbcb4fa aurel32
                     ctx.exception != POWERPC_EXCP_BRANCH)) {
7323 e1833e1f j_mayer
            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
7324 d26bfc9a j_mayer
        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
7325 2e70f6ef pbrook
                            (env->singlestep_enabled) ||
7326 2e70f6ef pbrook
                            num_insns >= max_insns)) {
7327 d26bfc9a j_mayer
            /* if we reach a page boundary or are single stepping, stop
7328 d26bfc9a j_mayer
             * generation
7329 d26bfc9a j_mayer
             */
7330 8dd4983c bellard
            break;
7331 76a66253 j_mayer
        }
7332 3fc6c082 bellard
#if defined (DO_SINGLE_STEP)
7333 3fc6c082 bellard
        break;
7334 3fc6c082 bellard
#endif
7335 3fc6c082 bellard
    }
7336 2e70f6ef pbrook
    if (tb->cflags & CF_LAST_IO)
7337 2e70f6ef pbrook
        gen_io_end();
7338 e1833e1f j_mayer
    if (ctx.exception == POWERPC_EXCP_NONE) {
7339 c1942362 bellard
        gen_goto_tb(&ctx, 0, ctx.nip);
7340 e1833e1f j_mayer
    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
7341 8cbcb4fa aurel32
        if (unlikely(env->singlestep_enabled)) {
7342 8cbcb4fa aurel32
            gen_update_nip(&ctx, ctx.nip);
7343 8cbcb4fa aurel32
            gen_op_debug();
7344 8cbcb4fa aurel32
        }
7345 76a66253 j_mayer
        /* Generate the return instruction */
7346 57fec1fe bellard
        tcg_gen_exit_tb(0);
7347 9a64fbe4 bellard
    }
7348 2e70f6ef pbrook
    gen_icount_end(tb, num_insns);
7349 79aceca5 bellard
    *gen_opc_ptr = INDEX_op_end;
7350 76a66253 j_mayer
    if (unlikely(search_pc)) {
7351 9a64fbe4 bellard
        j = gen_opc_ptr - gen_opc_buf;
7352 9a64fbe4 bellard
        lj++;
7353 9a64fbe4 bellard
        while (lj <= j)
7354 9a64fbe4 bellard
            gen_opc_instr_start[lj++] = 0;
7355 9a64fbe4 bellard
    } else {
7356 046d6672 bellard
        tb->size = ctx.nip - pc_start;
7357 2e70f6ef pbrook
        tb->icount = num_insns;
7358 9a64fbe4 bellard
    }
7359 d9bce9d9 j_mayer
#if defined(DEBUG_DISAS)
7360 9fddaa0c bellard
    if (loglevel & CPU_LOG_TB_CPU) {
7361 9a64fbe4 bellard
        fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
7362 7fe48483 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
7363 9fddaa0c bellard
    }
7364 9fddaa0c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
7365 76a66253 j_mayer
        int flags;
7366 237c0af0 j_mayer
        flags = env->bfd_mach;
7367 056401ea j_mayer
        flags |= little_endian << 16;
7368 0fa85d43 bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
7369 76a66253 j_mayer
        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
7370 79aceca5 bellard
        fprintf(logfile, "\n");
7371 9fddaa0c bellard
    }
7372 79aceca5 bellard
#endif
7373 79aceca5 bellard
}
7374 79aceca5 bellard
7375 2cfc5f17 ths
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
7376 79aceca5 bellard
{
7377 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 0);
7378 79aceca5 bellard
}
7379 79aceca5 bellard
7380 2cfc5f17 ths
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
7381 79aceca5 bellard
{
7382 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 1);
7383 79aceca5 bellard
}
7384 d2856f1a aurel32
7385 d2856f1a aurel32
void gen_pc_load(CPUState *env, TranslationBlock *tb,
7386 d2856f1a aurel32
                unsigned long searched_pc, int pc_pos, void *puc)
7387 d2856f1a aurel32
{
7388 d2856f1a aurel32
    int type, c;
7389 d2856f1a aurel32
    /* for PPC, we need to look at the micro operation to get the
7390 d2856f1a aurel32
     * access type */
7391 d2856f1a aurel32
    env->nip = gen_opc_pc[pc_pos];
7392 d2856f1a aurel32
    c = gen_opc_buf[pc_pos];
7393 d2856f1a aurel32
    switch(c) {
7394 d2856f1a aurel32
#if defined(CONFIG_USER_ONLY)
7395 d2856f1a aurel32
#define CASE3(op)\
7396 d2856f1a aurel32
    case INDEX_op_ ## op ## _raw
7397 d2856f1a aurel32
#else
7398 d2856f1a aurel32
#define CASE3(op)\
7399 d2856f1a aurel32
    case INDEX_op_ ## op ## _user:\
7400 d2856f1a aurel32
    case INDEX_op_ ## op ## _kernel:\
7401 d2856f1a aurel32
    case INDEX_op_ ## op ## _hypv
7402 d2856f1a aurel32
#endif
7403 d2856f1a aurel32
7404 d2856f1a aurel32
    CASE3(stfd):
7405 d2856f1a aurel32
    CASE3(stfs):
7406 d2856f1a aurel32
    CASE3(lfd):
7407 d2856f1a aurel32
    CASE3(lfs):
7408 d2856f1a aurel32
        type = ACCESS_FLOAT;
7409 d2856f1a aurel32
        break;
7410 d2856f1a aurel32
    CASE3(lwarx):
7411 d2856f1a aurel32
        type = ACCESS_RES;
7412 d2856f1a aurel32
        break;
7413 d2856f1a aurel32
    CASE3(stwcx):
7414 d2856f1a aurel32
        type = ACCESS_RES;
7415 d2856f1a aurel32
        break;
7416 d2856f1a aurel32
    CASE3(eciwx):
7417 d2856f1a aurel32
    CASE3(ecowx):
7418 d2856f1a aurel32
        type = ACCESS_EXT;
7419 d2856f1a aurel32
        break;
7420 d2856f1a aurel32
    default:
7421 d2856f1a aurel32
        type = ACCESS_INT;
7422 d2856f1a aurel32
        break;
7423 d2856f1a aurel32
    }
7424 d2856f1a aurel32
    env->access_type = type;
7425 d2856f1a aurel32
}