]> git.ipfire.org Git - thirdparty/qemu.git/blame - target-ppc/translate.c
ppc: Rework generation of priv and inval interrupts
[thirdparty/qemu.git] / target-ppc / translate.c
CommitLineData
79aceca5 1/*
3fc6c082 2 * PowerPC emulation for qemu: main translation routines.
5fafdf24 3 *
76a66253 4 * Copyright (c) 2003-2007 Jocelyn Mayer
90dc8812 5 * Copyright (C) 2011 Freescale Semiconductor, Inc.
79aceca5
FB
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
8167ee88 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
79aceca5 19 */
c6a1c22b 20
0d75590d 21#include "qemu/osdep.h"
79aceca5 22#include "cpu.h"
76cad711 23#include "disas/disas.h"
63c91552 24#include "exec/exec-all.h"
57fec1fe 25#include "tcg-op.h"
1de7afc9 26#include "qemu/host-utils.h"
f08b6170 27#include "exec/cpu_ldst.h"
79aceca5 28
2ef6175a
RH
29#include "exec/helper-proto.h"
30#include "exec/helper-gen.h"
a7812ae4 31
a7e30d84 32#include "trace-tcg.h"
508127e2 33#include "exec/log.h"
a7e30d84
LV
34
35
8cbcb4fa
AJ
36#define CPU_SINGLE_STEP 0x1
37#define CPU_BRANCH_STEP 0x2
38#define GDBSTUB_SINGLE_STEP 0x4
39
a750fc0b 40/* Include definitions for instructions classes and implementations flags */
9fddaa0c 41//#define PPC_DEBUG_DISAS
76a66253 42//#define DO_PPC_STATISTICS
79aceca5 43
d12d51d5 44#ifdef PPC_DEBUG_DISAS
93fcfe39 45# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
d12d51d5
AL
46#else
47# define LOG_DISAS(...) do { } while (0)
48#endif
a750fc0b
JM
49/*****************************************************************************/
50/* Code translation helpers */
c53be334 51
f78fb44e 52/* global register indexes */
1bcea73e 53static TCGv_env cpu_env;
1d542695 54static char cpu_reg_names[10*3 + 22*4 /* GPR */
1d542695 55 + 10*4 + 22*5 /* SPE GPRh */
a5e26afa 56 + 10*4 + 22*5 /* FPR */
47e4661c 57 + 2*(10*6 + 22*7) /* AVRh, AVRl */
472b24ce 58 + 10*5 + 22*6 /* VSR */
47e4661c 59 + 8*5 /* CRF */];
f78fb44e 60static TCGv cpu_gpr[32];
f78fb44e 61static TCGv cpu_gprh[32];
a7812ae4
PB
62static TCGv_i64 cpu_fpr[32];
63static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
472b24ce 64static TCGv_i64 cpu_vsr[32];
a7812ae4 65static TCGv_i32 cpu_crf[8];
bd568f18 66static TCGv cpu_nip;
6527f6ea 67static TCGv cpu_msr;
cfdcd37a
AJ
68static TCGv cpu_ctr;
69static TCGv cpu_lr;
697ab892
DG
70#if defined(TARGET_PPC64)
71static TCGv cpu_cfar;
72#endif
da91a00f 73static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca;
cf360a32 74static TCGv cpu_reserve;
30304420 75static TCGv cpu_fpscr;
a7859e89 76static TCGv_i32 cpu_access_type;
f78fb44e 77
022c62cb 78#include "exec/gen-icount.h"
2e70f6ef
PB
79
80void ppc_translate_init(void)
81{
f78fb44e
AJ
82 int i;
83 char* p;
2dc766da 84 size_t cpu_reg_names_size;
b2437bf2 85 static int done_init = 0;
f78fb44e 86
2e70f6ef
PB
87 if (done_init)
88 return;
f78fb44e 89
a7812ae4 90 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7c255043 91 tcg_ctx.tcg_env = cpu_env;
a7812ae4 92
f78fb44e 93 p = cpu_reg_names;
2dc766da 94 cpu_reg_names_size = sizeof(cpu_reg_names);
47e4661c
AJ
95
96 for (i = 0; i < 8; i++) {
2dc766da 97 snprintf(p, cpu_reg_names_size, "crf%d", i);
e1ccc054 98 cpu_crf[i] = tcg_global_mem_new_i32(cpu_env,
1328c2bf 99 offsetof(CPUPPCState, crf[i]), p);
47e4661c 100 p += 5;
2dc766da 101 cpu_reg_names_size -= 5;
47e4661c
AJ
102 }
103
f78fb44e 104 for (i = 0; i < 32; i++) {
2dc766da 105 snprintf(p, cpu_reg_names_size, "r%d", i);
e1ccc054 106 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
1328c2bf 107 offsetof(CPUPPCState, gpr[i]), p);
f78fb44e 108 p += (i < 10) ? 3 : 4;
2dc766da 109 cpu_reg_names_size -= (i < 10) ? 3 : 4;
2dc766da 110 snprintf(p, cpu_reg_names_size, "r%dH", i);
e1ccc054 111 cpu_gprh[i] = tcg_global_mem_new(cpu_env,
13b6a455 112 offsetof(CPUPPCState, gprh[i]), p);
f78fb44e 113 p += (i < 10) ? 4 : 5;
2dc766da 114 cpu_reg_names_size -= (i < 10) ? 4 : 5;
1d542695 115
2dc766da 116 snprintf(p, cpu_reg_names_size, "fp%d", i);
e1ccc054 117 cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
1328c2bf 118 offsetof(CPUPPCState, fpr[i]), p);
ec1ac72d 119 p += (i < 10) ? 4 : 5;
2dc766da 120 cpu_reg_names_size -= (i < 10) ? 4 : 5;
a5e26afa 121
2dc766da 122 snprintf(p, cpu_reg_names_size, "avr%dH", i);
e2542fe2 123#ifdef HOST_WORDS_BIGENDIAN
e1ccc054 124 cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env,
1328c2bf 125 offsetof(CPUPPCState, avr[i].u64[0]), p);
fe1e5c53 126#else
e1ccc054 127 cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env,
1328c2bf 128 offsetof(CPUPPCState, avr[i].u64[1]), p);
fe1e5c53 129#endif
1d542695 130 p += (i < 10) ? 6 : 7;
2dc766da 131 cpu_reg_names_size -= (i < 10) ? 6 : 7;
ec1ac72d 132
2dc766da 133 snprintf(p, cpu_reg_names_size, "avr%dL", i);
e2542fe2 134#ifdef HOST_WORDS_BIGENDIAN
e1ccc054 135 cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env,
1328c2bf 136 offsetof(CPUPPCState, avr[i].u64[1]), p);
fe1e5c53 137#else
e1ccc054 138 cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env,
1328c2bf 139 offsetof(CPUPPCState, avr[i].u64[0]), p);
fe1e5c53 140#endif
1d542695 141 p += (i < 10) ? 6 : 7;
2dc766da 142 cpu_reg_names_size -= (i < 10) ? 6 : 7;
472b24ce 143 snprintf(p, cpu_reg_names_size, "vsr%d", i);
e1ccc054
RH
144 cpu_vsr[i] = tcg_global_mem_new_i64(cpu_env,
145 offsetof(CPUPPCState, vsr[i]), p);
472b24ce
TM
146 p += (i < 10) ? 5 : 6;
147 cpu_reg_names_size -= (i < 10) ? 5 : 6;
f78fb44e 148 }
f10dc08e 149
e1ccc054 150 cpu_nip = tcg_global_mem_new(cpu_env,
1328c2bf 151 offsetof(CPUPPCState, nip), "nip");
bd568f18 152
e1ccc054 153 cpu_msr = tcg_global_mem_new(cpu_env,
1328c2bf 154 offsetof(CPUPPCState, msr), "msr");
6527f6ea 155
e1ccc054 156 cpu_ctr = tcg_global_mem_new(cpu_env,
1328c2bf 157 offsetof(CPUPPCState, ctr), "ctr");
cfdcd37a 158
e1ccc054 159 cpu_lr = tcg_global_mem_new(cpu_env,
1328c2bf 160 offsetof(CPUPPCState, lr), "lr");
cfdcd37a 161
697ab892 162#if defined(TARGET_PPC64)
e1ccc054 163 cpu_cfar = tcg_global_mem_new(cpu_env,
1328c2bf 164 offsetof(CPUPPCState, cfar), "cfar");
697ab892
DG
165#endif
166
e1ccc054 167 cpu_xer = tcg_global_mem_new(cpu_env,
1328c2bf 168 offsetof(CPUPPCState, xer), "xer");
e1ccc054 169 cpu_so = tcg_global_mem_new(cpu_env,
da91a00f 170 offsetof(CPUPPCState, so), "SO");
e1ccc054 171 cpu_ov = tcg_global_mem_new(cpu_env,
da91a00f 172 offsetof(CPUPPCState, ov), "OV");
e1ccc054 173 cpu_ca = tcg_global_mem_new(cpu_env,
da91a00f 174 offsetof(CPUPPCState, ca), "CA");
3d7b417e 175
e1ccc054 176 cpu_reserve = tcg_global_mem_new(cpu_env,
1328c2bf 177 offsetof(CPUPPCState, reserve_addr),
18b21a2f 178 "reserve_addr");
cf360a32 179
e1ccc054 180 cpu_fpscr = tcg_global_mem_new(cpu_env,
30304420 181 offsetof(CPUPPCState, fpscr), "fpscr");
e1571908 182
e1ccc054 183 cpu_access_type = tcg_global_mem_new_i32(cpu_env,
1328c2bf 184 offsetof(CPUPPCState, access_type), "access_type");
a7859e89 185
2e70f6ef
PB
186 done_init = 1;
187}
188
79aceca5 189/* internal defines */
69b058c8 190struct DisasContext {
79aceca5 191 struct TranslationBlock *tb;
0fa85d43 192 target_ulong nip;
79aceca5 193 uint32_t opcode;
9a64fbe4 194 uint32_t exception;
3cc62370 195 /* Routine used to access memory */
c47493f2 196 bool pr, hv;
c5a8d8f3 197 bool lazy_tlb_flush;
3cc62370 198 int mem_idx;
76db3ba4 199 int access_type;
3cc62370 200 /* Translation flags */
76db3ba4 201 int le_mode;
e22c357b 202 TCGMemOp default_tcg_memop_mask;
d9bce9d9
JM
203#if defined(TARGET_PPC64)
204 int sf_mode;
697ab892 205 int has_cfar;
9a64fbe4 206#endif
3cc62370 207 int fpu_enabled;
a9d9eb8f 208 int altivec_enabled;
1f29871c 209 int vsx_enabled;
0487d6a8 210 int spe_enabled;
69d1a937 211 int tm_enabled;
c227f099 212 ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
ea4e754f 213 int singlestep_enabled;
7d08d856
AJ
214 uint64_t insns_flags;
215 uint64_t insns_flags2;
69b058c8 216};
79aceca5 217
e22c357b
DK
218/* Return true iff byteswap is needed in a scalar memop */
219static inline bool need_byteswap(const DisasContext *ctx)
220{
221#if defined(TARGET_WORDS_BIGENDIAN)
222 return ctx->le_mode;
223#else
224 return !ctx->le_mode;
225#endif
226}
227
79482e5a
RH
228/* True when active word size < size of target_long. */
229#ifdef TARGET_PPC64
230# define NARROW_MODE(C) (!(C)->sf_mode)
231#else
232# define NARROW_MODE(C) 0
233#endif
234
c227f099 235struct opc_handler_t {
70560da7
FC
236 /* invalid bits for instruction 1 (Rc(opcode) == 0) */
237 uint32_t inval1;
238 /* invalid bits for instruction 2 (Rc(opcode) == 1) */
239 uint32_t inval2;
9a64fbe4 240 /* instruction type */
0487d6a8 241 uint64_t type;
a5858d7a
AG
242 /* extended instruction type */
243 uint64_t type2;
79aceca5
FB
244 /* handler */
245 void (*handler)(DisasContext *ctx);
a750fc0b 246#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
b55266b5 247 const char *oname;
a750fc0b
JM
248#endif
249#if defined(DO_PPC_STATISTICS)
76a66253
JM
250 uint64_t count;
251#endif
3fc6c082 252};
79aceca5 253
636aa200 254static inline void gen_reset_fpstatus(void)
7c58044c 255{
8e703949 256 gen_helper_reset_fpstatus(cpu_env);
7c58044c
JM
257}
258
7d45556e 259static inline void gen_compute_fprf(TCGv_i64 arg)
7c58044c 260{
58dd0a47 261 gen_helper_compute_fprf(cpu_env, arg);
7d45556e 262 gen_helper_float_check_status(cpu_env);
7c58044c
JM
263}
264
636aa200 265static inline void gen_set_access_type(DisasContext *ctx, int access_type)
a7859e89 266{
76db3ba4
AJ
267 if (ctx->access_type != access_type) {
268 tcg_gen_movi_i32(cpu_access_type, access_type);
269 ctx->access_type = access_type;
270 }
a7859e89
AJ
271}
272
636aa200 273static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
d9bce9d9 274{
e0c8f9ce
RH
275 if (NARROW_MODE(ctx)) {
276 nip = (uint32_t)nip;
277 }
278 tcg_gen_movi_tl(cpu_nip, nip);
d9bce9d9
JM
279}
280
7019cb3d
AK
281void gen_update_current_nip(void *opaque)
282{
283 DisasContext *ctx = opaque;
284
285 tcg_gen_movi_tl(cpu_nip, ctx->nip);
286}
287
636aa200 288static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
e06fcd75
AJ
289{
290 TCGv_i32 t0, t1;
291 if (ctx->exception == POWERPC_EXCP_NONE) {
292 gen_update_nip(ctx, ctx->nip);
293 }
294 t0 = tcg_const_i32(excp);
295 t1 = tcg_const_i32(error);
e5f17ac6 296 gen_helper_raise_exception_err(cpu_env, t0, t1);
e06fcd75
AJ
297 tcg_temp_free_i32(t0);
298 tcg_temp_free_i32(t1);
299 ctx->exception = (excp);
300}
e1833e1f 301
636aa200 302static inline void gen_exception(DisasContext *ctx, uint32_t excp)
e06fcd75
AJ
303{
304 TCGv_i32 t0;
305 if (ctx->exception == POWERPC_EXCP_NONE) {
306 gen_update_nip(ctx, ctx->nip);
307 }
308 t0 = tcg_const_i32(excp);
e5f17ac6 309 gen_helper_raise_exception(cpu_env, t0);
e06fcd75
AJ
310 tcg_temp_free_i32(t0);
311 ctx->exception = (excp);
312}
e1833e1f 313
636aa200 314static inline void gen_debug_exception(DisasContext *ctx)
e06fcd75
AJ
315{
316 TCGv_i32 t0;
5518f3a6 317
ee2b3994
SB
318 if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
319 (ctx->exception != POWERPC_EXCP_SYNC)) {
5518f3a6 320 gen_update_nip(ctx, ctx->nip);
ee2b3994 321 }
e06fcd75 322 t0 = tcg_const_i32(EXCP_DEBUG);
e5f17ac6 323 gen_helper_raise_exception(cpu_env, t0);
e06fcd75
AJ
324 tcg_temp_free_i32(t0);
325}
9a64fbe4 326
636aa200 327static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
e06fcd75 328{
9b2fadda
BH
329 /* Will be converted to program check if needed */
330 gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_INVAL | error);
331}
332
333static inline void gen_priv_exception(DisasContext *ctx, uint32_t error)
334{
335 gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_PRIV | error);
336}
337
338static inline void gen_hvpriv_exception(DisasContext *ctx, uint32_t error)
339{
340 /* Will be converted to program check if needed */
341 gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_PRIV | error);
e06fcd75 342}
a9d9eb8f 343
f24e5695 344/* Stop translation */
636aa200 345static inline void gen_stop_exception(DisasContext *ctx)
3fc6c082 346{
d9bce9d9 347 gen_update_nip(ctx, ctx->nip);
e1833e1f 348 ctx->exception = POWERPC_EXCP_STOP;
3fc6c082
FB
349}
350
466976d9 351#ifndef CONFIG_USER_ONLY
f24e5695 352/* No need to update nip here, as execution flow will change */
636aa200 353static inline void gen_sync_exception(DisasContext *ctx)
2be0071f 354{
e1833e1f 355 ctx->exception = POWERPC_EXCP_SYNC;
2be0071f 356}
466976d9 357#endif
2be0071f 358
79aceca5 359#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
a5858d7a
AG
360GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
361
362#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2) \
363GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
79aceca5 364
c7697e1f 365#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
a5858d7a
AG
366GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
367
368#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2) \
369GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
c7697e1f 370
c227f099 371typedef struct opcode_t {
79aceca5 372 unsigned char opc1, opc2, opc3;
1235fc06 373#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
18fba28c
FB
374 unsigned char pad[5];
375#else
376 unsigned char pad[1];
377#endif
c227f099 378 opc_handler_t handler;
b55266b5 379 const char *oname;
c227f099 380} opcode_t;
79aceca5 381
9b2fadda
BH
382/* Helpers for priv. check */
383#define GEN_PRIV \
384 do { \
385 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; \
386 } while (0)
387
388#if defined(CONFIG_USER_ONLY)
389#define CHK_HV GEN_PRIV
390#define CHK_SV GEN_PRIV
391#else
392#define CHK_HV \
393 do { \
394 if (unlikely(ctx->pr || !ctx->hv)) { \
395 GEN_PRIV; \
396 } \
397 } while (0)
398#define CHK_SV \
399 do { \
400 if (unlikely(ctx->pr)) { \
401 GEN_PRIV; \
402 } \
403 } while (0)
404#endif
405
406#define CHK_NONE
407
408
a750fc0b 409/*****************************************************************************/
79aceca5
FB
410/*** Instruction decoding ***/
411#define EXTRACT_HELPER(name, shift, nb) \
636aa200 412static inline uint32_t name(uint32_t opcode) \
79aceca5
FB
413{ \
414 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
415}
416
417#define EXTRACT_SHELPER(name, shift, nb) \
636aa200 418static inline int32_t name(uint32_t opcode) \
79aceca5 419{ \
18fba28c 420 return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
79aceca5
FB
421}
422
f9fc6d81
TM
423#define EXTRACT_HELPER_SPLIT(name, shift1, nb1, shift2, nb2) \
424static inline uint32_t name(uint32_t opcode) \
425{ \
426 return (((opcode >> (shift1)) & ((1 << (nb1)) - 1)) << nb2) | \
427 ((opcode >> (shift2)) & ((1 << (nb2)) - 1)); \
428}
79aceca5
FB
429/* Opcode part 1 */
430EXTRACT_HELPER(opc1, 26, 6);
431/* Opcode part 2 */
432EXTRACT_HELPER(opc2, 1, 5);
433/* Opcode part 3 */
434EXTRACT_HELPER(opc3, 6, 5);
435/* Update Cr0 flags */
436EXTRACT_HELPER(Rc, 0, 1);
a737d3eb
TM
437/* Update Cr6 flags (Altivec) */
438EXTRACT_HELPER(Rc21, 10, 1);
79aceca5
FB
439/* Destination */
440EXTRACT_HELPER(rD, 21, 5);
441/* Source */
442EXTRACT_HELPER(rS, 21, 5);
443/* First operand */
444EXTRACT_HELPER(rA, 16, 5);
445/* Second operand */
446EXTRACT_HELPER(rB, 11, 5);
447/* Third operand */
448EXTRACT_HELPER(rC, 6, 5);
449/*** Get CRn ***/
450EXTRACT_HELPER(crfD, 23, 3);
451EXTRACT_HELPER(crfS, 18, 3);
452EXTRACT_HELPER(crbD, 21, 5);
453EXTRACT_HELPER(crbA, 16, 5);
454EXTRACT_HELPER(crbB, 11, 5);
455/* SPR / TBL */
3fc6c082 456EXTRACT_HELPER(_SPR, 11, 10);
636aa200 457static inline uint32_t SPR(uint32_t opcode)
3fc6c082
FB
458{
459 uint32_t sprn = _SPR(opcode);
460
461 return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
462}
79aceca5 463/*** Get constants ***/
79aceca5
FB
464/* 16 bits signed immediate value */
465EXTRACT_SHELPER(SIMM, 0, 16);
466/* 16 bits unsigned immediate value */
467EXTRACT_HELPER(UIMM, 0, 16);
21d21583
AJ
468/* 5 bits signed immediate value */
469EXTRACT_HELPER(SIMM5, 16, 5);
27a4edb3
AJ
470/* 5 bits signed immediate value */
471EXTRACT_HELPER(UIMM5, 16, 5);
79aceca5
FB
472/* Bit count */
473EXTRACT_HELPER(NB, 11, 5);
474/* Shift count */
475EXTRACT_HELPER(SH, 11, 5);
cd633b10
AJ
476/* Vector shift count */
477EXTRACT_HELPER(VSH, 6, 4);
79aceca5
FB
478/* Mask start */
479EXTRACT_HELPER(MB, 6, 5);
480/* Mask end */
481EXTRACT_HELPER(ME, 1, 5);
fb0eaffc
FB
482/* Trap operand */
483EXTRACT_HELPER(TO, 21, 5);
79aceca5
FB
484
485EXTRACT_HELPER(CRM, 12, 8);
466976d9
PM
486
487#ifndef CONFIG_USER_ONLY
79aceca5 488EXTRACT_HELPER(SR, 16, 4);
466976d9 489#endif
7d08d856
AJ
490
491/* mtfsf/mtfsfi */
779f6590 492EXTRACT_HELPER(FPBF, 23, 3);
e4bb997e 493EXTRACT_HELPER(FPIMM, 12, 4);
779f6590 494EXTRACT_HELPER(FPL, 25, 1);
7d08d856
AJ
495EXTRACT_HELPER(FPFLM, 17, 8);
496EXTRACT_HELPER(FPW, 16, 1);
fb0eaffc 497
79aceca5 498/*** Jump target decoding ***/
79aceca5 499/* Immediate address */
636aa200 500static inline target_ulong LI(uint32_t opcode)
79aceca5
FB
501{
502 return (opcode >> 0) & 0x03FFFFFC;
503}
504
636aa200 505static inline uint32_t BD(uint32_t opcode)
79aceca5
FB
506{
507 return (opcode >> 0) & 0xFFFC;
508}
509
510EXTRACT_HELPER(BO, 21, 5);
511EXTRACT_HELPER(BI, 16, 5);
512/* Absolute/relative address */
513EXTRACT_HELPER(AA, 1, 1);
514/* Link */
515EXTRACT_HELPER(LK, 0, 1);
516
f0b01f02
TM
517/* DFP Z22-form */
518EXTRACT_HELPER(DCM, 10, 6)
519
520/* DFP Z23-form */
521EXTRACT_HELPER(RMC, 9, 2)
522
79aceca5 523/* Create a mask between <start> and <end> bits */
636aa200 524static inline target_ulong MASK(uint32_t start, uint32_t end)
79aceca5 525{
76a66253 526 target_ulong ret;
79aceca5 527
76a66253
JM
528#if defined(TARGET_PPC64)
529 if (likely(start == 0)) {
6f2d8978 530 ret = UINT64_MAX << (63 - end);
76a66253 531 } else if (likely(end == 63)) {
6f2d8978 532 ret = UINT64_MAX >> start;
76a66253
JM
533 }
534#else
535 if (likely(start == 0)) {
6f2d8978 536 ret = UINT32_MAX << (31 - end);
76a66253 537 } else if (likely(end == 31)) {
6f2d8978 538 ret = UINT32_MAX >> start;
76a66253
JM
539 }
540#endif
541 else {
542 ret = (((target_ulong)(-1ULL)) >> (start)) ^
543 (((target_ulong)(-1ULL) >> (end)) >> 1);
544 if (unlikely(start > end))
545 return ~ret;
546 }
79aceca5
FB
547
548 return ret;
549}
550
f9fc6d81
TM
551EXTRACT_HELPER_SPLIT(xT, 0, 1, 21, 5);
552EXTRACT_HELPER_SPLIT(xS, 0, 1, 21, 5);
553EXTRACT_HELPER_SPLIT(xA, 2, 1, 16, 5);
554EXTRACT_HELPER_SPLIT(xB, 1, 1, 11, 5);
551e3ef7 555EXTRACT_HELPER_SPLIT(xC, 3, 1, 6, 5);
f9fc6d81 556EXTRACT_HELPER(DM, 8, 2);
76c15fe0 557EXTRACT_HELPER(UIM, 16, 2);
acc42968 558EXTRACT_HELPER(SHW, 8, 2);
f0b01f02 559EXTRACT_HELPER(SP, 19, 2);
a750fc0b 560/*****************************************************************************/
a750fc0b 561/* PowerPC instructions table */
933dc6eb 562
76a66253 563#if defined(DO_PPC_STATISTICS)
a5858d7a 564#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 565{ \
79aceca5
FB
566 .opc1 = op1, \
567 .opc2 = op2, \
568 .opc3 = op3, \
18fba28c 569 .pad = { 0, }, \
79aceca5 570 .handler = { \
70560da7
FC
571 .inval1 = invl, \
572 .type = _typ, \
573 .type2 = _typ2, \
574 .handler = &gen_##name, \
575 .oname = stringify(name), \
576 }, \
577 .oname = stringify(name), \
578}
579#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \
580{ \
581 .opc1 = op1, \
582 .opc2 = op2, \
583 .opc3 = op3, \
584 .pad = { 0, }, \
585 .handler = { \
586 .inval1 = invl1, \
587 .inval2 = invl2, \
9a64fbe4 588 .type = _typ, \
a5858d7a 589 .type2 = _typ2, \
79aceca5 590 .handler = &gen_##name, \
76a66253 591 .oname = stringify(name), \
79aceca5 592 }, \
3fc6c082 593 .oname = stringify(name), \
79aceca5 594}
a5858d7a 595#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 596{ \
c7697e1f
JM
597 .opc1 = op1, \
598 .opc2 = op2, \
599 .opc3 = op3, \
600 .pad = { 0, }, \
601 .handler = { \
70560da7 602 .inval1 = invl, \
c7697e1f 603 .type = _typ, \
a5858d7a 604 .type2 = _typ2, \
c7697e1f
JM
605 .handler = &gen_##name, \
606 .oname = onam, \
607 }, \
608 .oname = onam, \
609}
76a66253 610#else
a5858d7a 611#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 612{ \
c7697e1f
JM
613 .opc1 = op1, \
614 .opc2 = op2, \
615 .opc3 = op3, \
616 .pad = { 0, }, \
617 .handler = { \
70560da7
FC
618 .inval1 = invl, \
619 .type = _typ, \
620 .type2 = _typ2, \
621 .handler = &gen_##name, \
622 }, \
623 .oname = stringify(name), \
624}
625#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \
626{ \
627 .opc1 = op1, \
628 .opc2 = op2, \
629 .opc3 = op3, \
630 .pad = { 0, }, \
631 .handler = { \
632 .inval1 = invl1, \
633 .inval2 = invl2, \
c7697e1f 634 .type = _typ, \
a5858d7a 635 .type2 = _typ2, \
c7697e1f 636 .handler = &gen_##name, \
5c55ff99
BS
637 }, \
638 .oname = stringify(name), \
639}
a5858d7a 640#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99
BS
641{ \
642 .opc1 = op1, \
643 .opc2 = op2, \
644 .opc3 = op3, \
645 .pad = { 0, }, \
646 .handler = { \
70560da7 647 .inval1 = invl, \
5c55ff99 648 .type = _typ, \
a5858d7a 649 .type2 = _typ2, \
5c55ff99
BS
650 .handler = &gen_##name, \
651 }, \
652 .oname = onam, \
653}
654#endif
2e610050 655
5c55ff99 656/* SPR load/store helpers */
636aa200 657static inline void gen_load_spr(TCGv t, int reg)
5c55ff99 658{
1328c2bf 659 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
5c55ff99 660}
2e610050 661
636aa200 662static inline void gen_store_spr(int reg, TCGv t)
5c55ff99 663{
1328c2bf 664 tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
5c55ff99 665}
2e610050 666
54623277 667/* Invalid instruction */
99e300ef 668static void gen_invalid(DisasContext *ctx)
9a64fbe4 669{
e06fcd75 670 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
9a64fbe4
FB
671}
672
c227f099 673static opc_handler_t invalid_handler = {
70560da7
FC
674 .inval1 = 0xFFFFFFFF,
675 .inval2 = 0xFFFFFFFF,
9a64fbe4 676 .type = PPC_NONE,
a5858d7a 677 .type2 = PPC_NONE,
79aceca5
FB
678 .handler = gen_invalid,
679};
680
e1571908
AJ
681/*** Integer comparison ***/
682
636aa200 683static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
e1571908 684{
2fdcb629
RH
685 TCGv t0 = tcg_temp_new();
686 TCGv_i32 t1 = tcg_temp_new_i32();
e1571908 687
da91a00f 688 tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
e1571908 689
2fdcb629
RH
690 tcg_gen_setcond_tl((s ? TCG_COND_LT: TCG_COND_LTU), t0, arg0, arg1);
691 tcg_gen_trunc_tl_i32(t1, t0);
692 tcg_gen_shli_i32(t1, t1, CRF_LT);
693 tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
694
695 tcg_gen_setcond_tl((s ? TCG_COND_GT: TCG_COND_GTU), t0, arg0, arg1);
696 tcg_gen_trunc_tl_i32(t1, t0);
697 tcg_gen_shli_i32(t1, t1, CRF_GT);
698 tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
699
700 tcg_gen_setcond_tl(TCG_COND_EQ, t0, arg0, arg1);
701 tcg_gen_trunc_tl_i32(t1, t0);
702 tcg_gen_shli_i32(t1, t1, CRF_EQ);
703 tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
704
705 tcg_temp_free(t0);
706 tcg_temp_free_i32(t1);
e1571908
AJ
707}
708
636aa200 709static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 710{
2fdcb629 711 TCGv t0 = tcg_const_tl(arg1);
ea363694
AJ
712 gen_op_cmp(arg0, t0, s, crf);
713 tcg_temp_free(t0);
e1571908
AJ
714}
715
636aa200 716static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
e1571908 717{
ea363694 718 TCGv t0, t1;
2fdcb629
RH
719 t0 = tcg_temp_new();
720 t1 = tcg_temp_new();
e1571908 721 if (s) {
ea363694
AJ
722 tcg_gen_ext32s_tl(t0, arg0);
723 tcg_gen_ext32s_tl(t1, arg1);
e1571908 724 } else {
ea363694
AJ
725 tcg_gen_ext32u_tl(t0, arg0);
726 tcg_gen_ext32u_tl(t1, arg1);
e1571908 727 }
ea363694
AJ
728 gen_op_cmp(t0, t1, s, crf);
729 tcg_temp_free(t1);
730 tcg_temp_free(t0);
e1571908
AJ
731}
732
636aa200 733static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 734{
2fdcb629 735 TCGv t0 = tcg_const_tl(arg1);
ea363694
AJ
736 gen_op_cmp32(arg0, t0, s, crf);
737 tcg_temp_free(t0);
e1571908 738}
e1571908 739
636aa200 740static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
e1571908 741{
02765534 742 if (NARROW_MODE(ctx)) {
e1571908 743 gen_op_cmpi32(reg, 0, 1, 0);
02765534 744 } else {
e1571908 745 gen_op_cmpi(reg, 0, 1, 0);
02765534 746 }
e1571908
AJ
747}
748
749/* cmp */
99e300ef 750static void gen_cmp(DisasContext *ctx)
e1571908 751{
36f48d9c 752 if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
e1571908
AJ
753 gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
754 1, crfD(ctx->opcode));
36f48d9c
AG
755 } else {
756 gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
757 1, crfD(ctx->opcode));
02765534 758 }
e1571908
AJ
759}
760
761/* cmpi */
99e300ef 762static void gen_cmpi(DisasContext *ctx)
e1571908 763{
36f48d9c 764 if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
e1571908
AJ
765 gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
766 1, crfD(ctx->opcode));
36f48d9c
AG
767 } else {
768 gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
769 1, crfD(ctx->opcode));
02765534 770 }
e1571908
AJ
771}
772
773/* cmpl */
99e300ef 774static void gen_cmpl(DisasContext *ctx)
e1571908 775{
36f48d9c 776 if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
e1571908
AJ
777 gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
778 0, crfD(ctx->opcode));
36f48d9c
AG
779 } else {
780 gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
781 0, crfD(ctx->opcode));
02765534 782 }
e1571908
AJ
783}
784
785/* cmpli */
99e300ef 786static void gen_cmpli(DisasContext *ctx)
e1571908 787{
36f48d9c 788 if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
e1571908
AJ
789 gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
790 0, crfD(ctx->opcode));
36f48d9c
AG
791 } else {
792 gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
793 0, crfD(ctx->opcode));
02765534 794 }
e1571908
AJ
795}
796
797/* isel (PowerPC 2.03 specification) */
99e300ef 798static void gen_isel(DisasContext *ctx)
e1571908 799{
e1571908 800 uint32_t bi = rC(ctx->opcode);
24f9cd95
RH
801 uint32_t mask = 0x08 >> (bi & 0x03);
802 TCGv t0 = tcg_temp_new();
803 TCGv zr;
e1571908 804
24f9cd95
RH
805 tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]);
806 tcg_gen_andi_tl(t0, t0, mask);
807
808 zr = tcg_const_tl(0);
809 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rD(ctx->opcode)], t0, zr,
810 rA(ctx->opcode) ? cpu_gpr[rA(ctx->opcode)] : zr,
811 cpu_gpr[rB(ctx->opcode)]);
812 tcg_temp_free(zr);
813 tcg_temp_free(t0);
e1571908
AJ
814}
815
fcfda20f
AJ
816/* cmpb: PowerPC 2.05 specification */
817static void gen_cmpb(DisasContext *ctx)
818{
819 gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
820 cpu_gpr[rB(ctx->opcode)]);
821}
822
79aceca5 823/*** Integer arithmetic ***/
79aceca5 824
636aa200
BS
825static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
826 TCGv arg1, TCGv arg2, int sub)
74637406 827{
ffe30937 828 TCGv t0 = tcg_temp_new();
79aceca5 829
8e7a6db9 830 tcg_gen_xor_tl(cpu_ov, arg0, arg2);
74637406 831 tcg_gen_xor_tl(t0, arg1, arg2);
ffe30937
RH
832 if (sub) {
833 tcg_gen_and_tl(cpu_ov, cpu_ov, t0);
834 } else {
835 tcg_gen_andc_tl(cpu_ov, cpu_ov, t0);
836 }
837 tcg_temp_free(t0);
02765534 838 if (NARROW_MODE(ctx)) {
ffe30937
RH
839 tcg_gen_ext32s_tl(cpu_ov, cpu_ov);
840 }
ffe30937
RH
841 tcg_gen_shri_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1);
842 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
79aceca5
FB
843}
844
74637406 845/* Common add function */
636aa200 846static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
b5a73f8d
RH
847 TCGv arg2, bool add_ca, bool compute_ca,
848 bool compute_ov, bool compute_rc0)
74637406 849{
b5a73f8d 850 TCGv t0 = ret;
d9bce9d9 851
752d634e 852 if (compute_ca || compute_ov) {
146de60d 853 t0 = tcg_temp_new();
74637406 854 }
79aceca5 855
da91a00f 856 if (compute_ca) {
79482e5a 857 if (NARROW_MODE(ctx)) {
752d634e
RH
858 /* Caution: a non-obvious corner case of the spec is that we
859 must produce the *entire* 64-bit addition, but produce the
860 carry into bit 32. */
79482e5a 861 TCGv t1 = tcg_temp_new();
752d634e
RH
862 tcg_gen_xor_tl(t1, arg1, arg2); /* add without carry */
863 tcg_gen_add_tl(t0, arg1, arg2);
79482e5a
RH
864 if (add_ca) {
865 tcg_gen_add_tl(t0, t0, cpu_ca);
866 }
752d634e
RH
867 tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changed w/ carry */
868 tcg_temp_free(t1);
869 tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */
870 tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
b5a73f8d 871 } else {
79482e5a
RH
872 TCGv zero = tcg_const_tl(0);
873 if (add_ca) {
874 tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero);
875 tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero);
876 } else {
877 tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero);
878 }
879 tcg_temp_free(zero);
b5a73f8d 880 }
b5a73f8d
RH
881 } else {
882 tcg_gen_add_tl(t0, arg1, arg2);
883 if (add_ca) {
884 tcg_gen_add_tl(t0, t0, cpu_ca);
885 }
da91a00f 886 }
79aceca5 887
74637406
AJ
888 if (compute_ov) {
889 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
890 }
b5a73f8d 891 if (unlikely(compute_rc0)) {
74637406 892 gen_set_Rc0(ctx, t0);
b5a73f8d 893 }
74637406 894
a7812ae4 895 if (!TCGV_EQUAL(t0, ret)) {
74637406
AJ
896 tcg_gen_mov_tl(ret, t0);
897 tcg_temp_free(t0);
898 }
39dd32ee 899}
74637406
AJ
900/* Add functions with two operands */
901#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
b5a73f8d 902static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
903{ \
904 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
905 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
b5a73f8d 906 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
907}
908/* Add functions with one operand and one immediate */
909#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
910 add_ca, compute_ca, compute_ov) \
b5a73f8d 911static void glue(gen_, name)(DisasContext *ctx) \
74637406 912{ \
b5a73f8d 913 TCGv t0 = tcg_const_tl(const_val); \
74637406
AJ
914 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
915 cpu_gpr[rA(ctx->opcode)], t0, \
b5a73f8d 916 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
917 tcg_temp_free(t0); \
918}
919
920/* add add. addo addo. */
921GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
922GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
923/* addc addc. addco addco. */
924GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
925GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
926/* adde adde. addeo addeo. */
927GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
928GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
929/* addme addme. addmeo addmeo. */
930GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
931GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
932/* addze addze. addzeo addzeo.*/
933GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
934GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
935/* addi */
99e300ef 936static void gen_addi(DisasContext *ctx)
d9bce9d9 937{
74637406
AJ
938 target_long simm = SIMM(ctx->opcode);
939
940 if (rA(ctx->opcode) == 0) {
941 /* li case */
942 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
943 } else {
b5a73f8d
RH
944 tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
945 cpu_gpr[rA(ctx->opcode)], simm);
74637406 946 }
d9bce9d9 947}
74637406 948/* addic addic.*/
b5a73f8d 949static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
d9bce9d9 950{
b5a73f8d
RH
951 TCGv c = tcg_const_tl(SIMM(ctx->opcode));
952 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
953 c, 0, 1, 0, compute_rc0);
954 tcg_temp_free(c);
d9bce9d9 955}
99e300ef
BS
956
957static void gen_addic(DisasContext *ctx)
d9bce9d9 958{
b5a73f8d 959 gen_op_addic(ctx, 0);
d9bce9d9 960}
e8eaa2c0
BS
961
962static void gen_addic_(DisasContext *ctx)
d9bce9d9 963{
b5a73f8d 964 gen_op_addic(ctx, 1);
d9bce9d9 965}
99e300ef 966
54623277 967/* addis */
99e300ef 968static void gen_addis(DisasContext *ctx)
d9bce9d9 969{
74637406
AJ
970 target_long simm = SIMM(ctx->opcode);
971
972 if (rA(ctx->opcode) == 0) {
973 /* lis case */
974 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
975 } else {
b5a73f8d
RH
976 tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
977 cpu_gpr[rA(ctx->opcode)], simm << 16);
74637406 978 }
d9bce9d9 979}
74637406 980
636aa200
BS
981static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
982 TCGv arg2, int sign, int compute_ov)
d9bce9d9 983{
42a268c2
RH
984 TCGLabel *l1 = gen_new_label();
985 TCGLabel *l2 = gen_new_label();
a7812ae4
PB
986 TCGv_i32 t0 = tcg_temp_local_new_i32();
987 TCGv_i32 t1 = tcg_temp_local_new_i32();
74637406 988
2ef1b120
AJ
989 tcg_gen_trunc_tl_i32(t0, arg1);
990 tcg_gen_trunc_tl_i32(t1, arg2);
991 tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
74637406 992 if (sign) {
42a268c2 993 TCGLabel *l3 = gen_new_label();
2ef1b120
AJ
994 tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
995 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
74637406 996 gen_set_label(l3);
2ef1b120 997 tcg_gen_div_i32(t0, t0, t1);
74637406 998 } else {
2ef1b120 999 tcg_gen_divu_i32(t0, t0, t1);
74637406
AJ
1000 }
1001 if (compute_ov) {
da91a00f 1002 tcg_gen_movi_tl(cpu_ov, 0);
74637406
AJ
1003 }
1004 tcg_gen_br(l2);
1005 gen_set_label(l1);
1006 if (sign) {
2ef1b120 1007 tcg_gen_sari_i32(t0, t0, 31);
74637406
AJ
1008 } else {
1009 tcg_gen_movi_i32(t0, 0);
1010 }
1011 if (compute_ov) {
da91a00f
RH
1012 tcg_gen_movi_tl(cpu_ov, 1);
1013 tcg_gen_movi_tl(cpu_so, 1);
74637406
AJ
1014 }
1015 gen_set_label(l2);
2ef1b120 1016 tcg_gen_extu_i32_tl(ret, t0);
a7812ae4
PB
1017 tcg_temp_free_i32(t0);
1018 tcg_temp_free_i32(t1);
74637406
AJ
1019 if (unlikely(Rc(ctx->opcode) != 0))
1020 gen_set_Rc0(ctx, ret);
d9bce9d9 1021}
74637406
AJ
1022/* Div functions */
1023#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
99e300ef 1024static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
1025{ \
1026 gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)], \
1027 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1028 sign, compute_ov); \
1029}
1030/* divwu divwu. divwuo divwuo. */
1031GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
1032GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
1033/* divw divw. divwo divwo. */
1034GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
1035GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
98d1eb27
TM
1036
1037/* div[wd]eu[o][.] */
1038#define GEN_DIVE(name, hlpr, compute_ov) \
1039static void gen_##name(DisasContext *ctx) \
1040{ \
1041 TCGv_i32 t0 = tcg_const_i32(compute_ov); \
1042 gen_helper_##hlpr(cpu_gpr[rD(ctx->opcode)], cpu_env, \
1043 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0); \
1044 tcg_temp_free_i32(t0); \
1045 if (unlikely(Rc(ctx->opcode) != 0)) { \
1046 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); \
1047 } \
1048}
1049
6a4fda33
TM
1050GEN_DIVE(divweu, divweu, 0);
1051GEN_DIVE(divweuo, divweu, 1);
a98eb9e9
TM
1052GEN_DIVE(divwe, divwe, 0);
1053GEN_DIVE(divweo, divwe, 1);
6a4fda33 1054
d9bce9d9 1055#if defined(TARGET_PPC64)
636aa200
BS
1056static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
1057 TCGv arg2, int sign, int compute_ov)
d9bce9d9 1058{
42a268c2
RH
1059 TCGLabel *l1 = gen_new_label();
1060 TCGLabel *l2 = gen_new_label();
74637406
AJ
1061
1062 tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
1063 if (sign) {
42a268c2 1064 TCGLabel *l3 = gen_new_label();
74637406
AJ
1065 tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
1066 tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
1067 gen_set_label(l3);
74637406
AJ
1068 tcg_gen_div_i64(ret, arg1, arg2);
1069 } else {
1070 tcg_gen_divu_i64(ret, arg1, arg2);
1071 }
1072 if (compute_ov) {
da91a00f 1073 tcg_gen_movi_tl(cpu_ov, 0);
74637406
AJ
1074 }
1075 tcg_gen_br(l2);
1076 gen_set_label(l1);
1077 if (sign) {
1078 tcg_gen_sari_i64(ret, arg1, 63);
1079 } else {
1080 tcg_gen_movi_i64(ret, 0);
1081 }
1082 if (compute_ov) {
da91a00f
RH
1083 tcg_gen_movi_tl(cpu_ov, 1);
1084 tcg_gen_movi_tl(cpu_so, 1);
74637406
AJ
1085 }
1086 gen_set_label(l2);
1087 if (unlikely(Rc(ctx->opcode) != 0))
1088 gen_set_Rc0(ctx, ret);
d9bce9d9 1089}
74637406 1090#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
99e300ef 1091static void glue(gen_, name)(DisasContext *ctx) \
74637406 1092{ \
2ef1b120
AJ
1093 gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)], \
1094 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1095 sign, compute_ov); \
74637406
AJ
1096}
1097/* divwu divwu. divwuo divwuo. */
1098GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1099GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1100/* divw divw. divwo divwo. */
1101GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1102GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
98d1eb27
TM
1103
1104GEN_DIVE(divdeu, divdeu, 0);
1105GEN_DIVE(divdeuo, divdeu, 1);
e44259b6
TM
1106GEN_DIVE(divde, divde, 0);
1107GEN_DIVE(divdeo, divde, 1);
d9bce9d9 1108#endif
74637406
AJ
1109
1110/* mulhw mulhw. */
99e300ef 1111static void gen_mulhw(DisasContext *ctx)
d9bce9d9 1112{
23ad1d5d
RH
1113 TCGv_i32 t0 = tcg_temp_new_i32();
1114 TCGv_i32 t1 = tcg_temp_new_i32();
74637406 1115
23ad1d5d
RH
1116 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1117 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1118 tcg_gen_muls2_i32(t0, t1, t0, t1);
1119 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1120 tcg_temp_free_i32(t0);
1121 tcg_temp_free_i32(t1);
74637406
AJ
1122 if (unlikely(Rc(ctx->opcode) != 0))
1123 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1124}
99e300ef 1125
54623277 1126/* mulhwu mulhwu. */
99e300ef 1127static void gen_mulhwu(DisasContext *ctx)
d9bce9d9 1128{
23ad1d5d
RH
1129 TCGv_i32 t0 = tcg_temp_new_i32();
1130 TCGv_i32 t1 = tcg_temp_new_i32();
74637406 1131
23ad1d5d
RH
1132 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1133 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1134 tcg_gen_mulu2_i32(t0, t1, t0, t1);
1135 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1136 tcg_temp_free_i32(t0);
1137 tcg_temp_free_i32(t1);
74637406
AJ
1138 if (unlikely(Rc(ctx->opcode) != 0))
1139 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1140}
99e300ef 1141
54623277 1142/* mullw mullw. */
99e300ef 1143static void gen_mullw(DisasContext *ctx)
d9bce9d9 1144{
1fa74845
TM
1145#if defined(TARGET_PPC64)
1146 TCGv_i64 t0, t1;
1147 t0 = tcg_temp_new_i64();
1148 t1 = tcg_temp_new_i64();
1149 tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1150 tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1151 tcg_gen_mul_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
1152 tcg_temp_free(t0);
1153 tcg_temp_free(t1);
1154#else
03039e5e
TM
1155 tcg_gen_mul_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1156 cpu_gpr[rB(ctx->opcode)]);
1fa74845 1157#endif
74637406
AJ
1158 if (unlikely(Rc(ctx->opcode) != 0))
1159 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1160}
99e300ef 1161
54623277 1162/* mullwo mullwo. */
99e300ef 1163static void gen_mullwo(DisasContext *ctx)
d9bce9d9 1164{
e4a2c846
RH
1165 TCGv_i32 t0 = tcg_temp_new_i32();
1166 TCGv_i32 t1 = tcg_temp_new_i32();
74637406 1167
e4a2c846
RH
1168 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1169 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1170 tcg_gen_muls2_i32(t0, t1, t0, t1);
f11ebbf8 1171#if defined(TARGET_PPC64)
26977876
TM
1172 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
1173#else
1174 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], t0);
f11ebbf8 1175#endif
e4a2c846
RH
1176
1177 tcg_gen_sari_i32(t0, t0, 31);
1178 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1);
1179 tcg_gen_extu_i32_tl(cpu_ov, t0);
1180 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1181
1182 tcg_temp_free_i32(t0);
1183 tcg_temp_free_i32(t1);
74637406
AJ
1184 if (unlikely(Rc(ctx->opcode) != 0))
1185 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1186}
99e300ef 1187
54623277 1188/* mulli */
99e300ef 1189static void gen_mulli(DisasContext *ctx)
d9bce9d9 1190{
74637406
AJ
1191 tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1192 SIMM(ctx->opcode));
d9bce9d9 1193}
23ad1d5d 1194
d9bce9d9 1195#if defined(TARGET_PPC64)
74637406 1196/* mulhd mulhd. */
23ad1d5d
RH
1197static void gen_mulhd(DisasContext *ctx)
1198{
1199 TCGv lo = tcg_temp_new();
1200 tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)],
1201 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1202 tcg_temp_free(lo);
1203 if (unlikely(Rc(ctx->opcode) != 0)) {
1204 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1205 }
1206}
1207
74637406 1208/* mulhdu mulhdu. */
23ad1d5d
RH
1209static void gen_mulhdu(DisasContext *ctx)
1210{
1211 TCGv lo = tcg_temp_new();
1212 tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)],
1213 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1214 tcg_temp_free(lo);
1215 if (unlikely(Rc(ctx->opcode) != 0)) {
1216 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1217 }
1218}
99e300ef 1219
54623277 1220/* mulld mulld. */
99e300ef 1221static void gen_mulld(DisasContext *ctx)
d9bce9d9 1222{
74637406
AJ
1223 tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1224 cpu_gpr[rB(ctx->opcode)]);
1225 if (unlikely(Rc(ctx->opcode) != 0))
1226 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1227}
d15f74fb 1228
74637406 1229/* mulldo mulldo. */
d15f74fb
BS
1230static void gen_mulldo(DisasContext *ctx)
1231{
22ffad31
TM
1232 TCGv_i64 t0 = tcg_temp_new_i64();
1233 TCGv_i64 t1 = tcg_temp_new_i64();
1234
1235 tcg_gen_muls2_i64(t0, t1, cpu_gpr[rA(ctx->opcode)],
1236 cpu_gpr[rB(ctx->opcode)]);
1237 tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], t0);
1238
1239 tcg_gen_sari_i64(t0, t0, 63);
1240 tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1);
1241 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1242
1243 tcg_temp_free_i64(t0);
1244 tcg_temp_free_i64(t1);
1245
d15f74fb
BS
1246 if (unlikely(Rc(ctx->opcode) != 0)) {
1247 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1248 }
1249}
d9bce9d9 1250#endif
74637406 1251
74637406 1252/* Common subf function */
636aa200 1253static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
b5a73f8d
RH
1254 TCGv arg2, bool add_ca, bool compute_ca,
1255 bool compute_ov, bool compute_rc0)
79aceca5 1256{
b5a73f8d 1257 TCGv t0 = ret;
79aceca5 1258
752d634e 1259 if (compute_ca || compute_ov) {
b5a73f8d 1260 t0 = tcg_temp_new();
da91a00f 1261 }
74637406 1262
79482e5a
RH
1263 if (compute_ca) {
1264 /* dest = ~arg1 + arg2 [+ ca]. */
1265 if (NARROW_MODE(ctx)) {
752d634e
RH
1266 /* Caution: a non-obvious corner case of the spec is that we
1267 must produce the *entire* 64-bit addition, but produce the
1268 carry into bit 32. */
79482e5a 1269 TCGv inv1 = tcg_temp_new();
752d634e 1270 TCGv t1 = tcg_temp_new();
79482e5a 1271 tcg_gen_not_tl(inv1, arg1);
79482e5a 1272 if (add_ca) {
752d634e 1273 tcg_gen_add_tl(t0, arg2, cpu_ca);
79482e5a 1274 } else {
752d634e 1275 tcg_gen_addi_tl(t0, arg2, 1);
79482e5a 1276 }
752d634e 1277 tcg_gen_xor_tl(t1, arg2, inv1); /* add without carry */
79482e5a 1278 tcg_gen_add_tl(t0, t0, inv1);
c80d1df5 1279 tcg_temp_free(inv1);
752d634e
RH
1280 tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changes w/ carry */
1281 tcg_temp_free(t1);
1282 tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */
1283 tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
79482e5a 1284 } else if (add_ca) {
08f4a0f7
RH
1285 TCGv zero, inv1 = tcg_temp_new();
1286 tcg_gen_not_tl(inv1, arg1);
b5a73f8d
RH
1287 zero = tcg_const_tl(0);
1288 tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero);
08f4a0f7 1289 tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero);
b5a73f8d 1290 tcg_temp_free(zero);
08f4a0f7 1291 tcg_temp_free(inv1);
b5a73f8d 1292 } else {
79482e5a 1293 tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
b5a73f8d 1294 tcg_gen_sub_tl(t0, arg2, arg1);
b5a73f8d 1295 }
79482e5a
RH
1296 } else if (add_ca) {
1297 /* Since we're ignoring carry-out, we can simplify the
1298 standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1. */
1299 tcg_gen_sub_tl(t0, arg2, arg1);
1300 tcg_gen_add_tl(t0, t0, cpu_ca);
1301 tcg_gen_subi_tl(t0, t0, 1);
79aceca5 1302 } else {
b5a73f8d 1303 tcg_gen_sub_tl(t0, arg2, arg1);
74637406 1304 }
b5a73f8d 1305
74637406
AJ
1306 if (compute_ov) {
1307 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1308 }
b5a73f8d 1309 if (unlikely(compute_rc0)) {
74637406 1310 gen_set_Rc0(ctx, t0);
b5a73f8d 1311 }
74637406 1312
a7812ae4 1313 if (!TCGV_EQUAL(t0, ret)) {
74637406
AJ
1314 tcg_gen_mov_tl(ret, t0);
1315 tcg_temp_free(t0);
79aceca5 1316 }
79aceca5 1317}
74637406
AJ
1318/* Sub functions with Two operands functions */
1319#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
b5a73f8d 1320static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
1321{ \
1322 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1323 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
b5a73f8d 1324 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
1325}
1326/* Sub functions with one operand and one immediate */
1327#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
1328 add_ca, compute_ca, compute_ov) \
b5a73f8d 1329static void glue(gen_, name)(DisasContext *ctx) \
74637406 1330{ \
b5a73f8d 1331 TCGv t0 = tcg_const_tl(const_val); \
74637406
AJ
1332 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1333 cpu_gpr[rA(ctx->opcode)], t0, \
b5a73f8d 1334 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
1335 tcg_temp_free(t0); \
1336}
1337/* subf subf. subfo subfo. */
1338GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1339GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1340/* subfc subfc. subfco subfco. */
1341GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1342GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1343/* subfe subfe. subfeo subfo. */
1344GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1345GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1346/* subfme subfme. subfmeo subfmeo. */
1347GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1348GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1349/* subfze subfze. subfzeo subfzeo.*/
1350GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1351GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
99e300ef 1352
54623277 1353/* subfic */
99e300ef 1354static void gen_subfic(DisasContext *ctx)
79aceca5 1355{
b5a73f8d
RH
1356 TCGv c = tcg_const_tl(SIMM(ctx->opcode));
1357 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1358 c, 0, 1, 0, 0);
1359 tcg_temp_free(c);
79aceca5
FB
1360}
1361
fd3f0081
RH
1362/* neg neg. nego nego. */
1363static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
1364{
1365 TCGv zero = tcg_const_tl(0);
1366 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1367 zero, 0, 0, compute_ov, Rc(ctx->opcode));
1368 tcg_temp_free(zero);
1369}
1370
1371static void gen_neg(DisasContext *ctx)
1372{
1373 gen_op_arith_neg(ctx, 0);
1374}
1375
1376static void gen_nego(DisasContext *ctx)
1377{
1378 gen_op_arith_neg(ctx, 1);
1379}
1380
79aceca5 1381/*** Integer logical ***/
26d67362 1382#define GEN_LOGICAL2(name, tcg_op, opc, type) \
99e300ef 1383static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 1384{ \
26d67362
AJ
1385 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \
1386 cpu_gpr[rB(ctx->opcode)]); \
76a66253 1387 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 1388 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5 1389}
79aceca5 1390
26d67362 1391#define GEN_LOGICAL1(name, tcg_op, opc, type) \
99e300ef 1392static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 1393{ \
26d67362 1394 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \
76a66253 1395 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 1396 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5
FB
1397}
1398
1399/* and & and. */
26d67362 1400GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
79aceca5 1401/* andc & andc. */
26d67362 1402GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
e8eaa2c0 1403
54623277 1404/* andi. */
e8eaa2c0 1405static void gen_andi_(DisasContext *ctx)
79aceca5 1406{
26d67362
AJ
1407 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1408 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1409}
e8eaa2c0 1410
54623277 1411/* andis. */
e8eaa2c0 1412static void gen_andis_(DisasContext *ctx)
79aceca5 1413{
26d67362
AJ
1414 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1415 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1416}
99e300ef 1417
54623277 1418/* cntlzw */
99e300ef 1419static void gen_cntlzw(DisasContext *ctx)
26d67362 1420{
a7812ae4 1421 gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
26d67362 1422 if (unlikely(Rc(ctx->opcode) != 0))
2e31f5d3 1423 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
26d67362 1424}
79aceca5 1425/* eqv & eqv. */
26d67362 1426GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
79aceca5 1427/* extsb & extsb. */
26d67362 1428GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
79aceca5 1429/* extsh & extsh. */
26d67362 1430GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
79aceca5 1431/* nand & nand. */
26d67362 1432GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
79aceca5 1433/* nor & nor. */
26d67362 1434GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
99e300ef 1435
7f2b1744 1436#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
b68e60e6
BH
1437static void gen_pause(DisasContext *ctx)
1438{
1439 TCGv_i32 t0 = tcg_const_i32(0);
1440 tcg_gen_st_i32(t0, cpu_env,
1441 -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
1442 tcg_temp_free_i32(t0);
1443
1444 /* Stop translation, this gives other CPUs a chance to run */
1445 gen_exception_err(ctx, EXCP_HLT, 1);
1446}
1447#endif /* defined(TARGET_PPC64) */
1448
54623277 1449/* or & or. */
99e300ef 1450static void gen_or(DisasContext *ctx)
9a64fbe4 1451{
76a66253
JM
1452 int rs, ra, rb;
1453
1454 rs = rS(ctx->opcode);
1455 ra = rA(ctx->opcode);
1456 rb = rB(ctx->opcode);
1457 /* Optimisation for mr. ri case */
1458 if (rs != ra || rs != rb) {
26d67362
AJ
1459 if (rs != rb)
1460 tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1461 else
1462 tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
76a66253 1463 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1464 gen_set_Rc0(ctx, cpu_gpr[ra]);
76a66253 1465 } else if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 1466 gen_set_Rc0(ctx, cpu_gpr[rs]);
c80f84e3
JM
1467#if defined(TARGET_PPC64)
1468 } else {
26d67362
AJ
1469 int prio = 0;
1470
c80f84e3
JM
1471 switch (rs) {
1472 case 1:
1473 /* Set process priority to low */
26d67362 1474 prio = 2;
c80f84e3
JM
1475 break;
1476 case 6:
1477 /* Set process priority to medium-low */
26d67362 1478 prio = 3;
c80f84e3
JM
1479 break;
1480 case 2:
1481 /* Set process priority to normal */
26d67362 1482 prio = 4;
c80f84e3 1483 break;
be147d08
JM
1484#if !defined(CONFIG_USER_ONLY)
1485 case 31:
c47493f2 1486 if (!ctx->pr) {
be147d08 1487 /* Set process priority to very low */
26d67362 1488 prio = 1;
be147d08
JM
1489 }
1490 break;
1491 case 5:
c47493f2 1492 if (!ctx->pr) {
be147d08 1493 /* Set process priority to medium-hight */
26d67362 1494 prio = 5;
be147d08
JM
1495 }
1496 break;
1497 case 3:
c47493f2 1498 if (!ctx->pr) {
be147d08 1499 /* Set process priority to high */
26d67362 1500 prio = 6;
be147d08
JM
1501 }
1502 break;
be147d08 1503 case 7:
b68e60e6 1504 if (ctx->hv && !ctx->pr) {
be147d08 1505 /* Set process priority to very high */
26d67362 1506 prio = 7;
be147d08
JM
1507 }
1508 break;
be147d08 1509#endif
c80f84e3
JM
1510 default:
1511 /* nop */
1512 break;
1513 }
26d67362 1514 if (prio) {
a7812ae4 1515 TCGv t0 = tcg_temp_new();
54cdcae6 1516 gen_load_spr(t0, SPR_PPR);
ea363694
AJ
1517 tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1518 tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
54cdcae6 1519 gen_store_spr(SPR_PPR, t0);
ea363694 1520 tcg_temp_free(t0);
b68e60e6
BH
1521 /* Pause us out of TCG otherwise spin loops with smt_low
1522 * eat too much CPU and the kernel hangs
1523 */
7f2b1744 1524#if !defined(CONFIG_USER_ONLY)
b68e60e6 1525 gen_pause(ctx);
7f2b1744 1526#endif
26d67362 1527 }
c80f84e3 1528#endif
9a64fbe4 1529 }
9a64fbe4 1530}
79aceca5 1531/* orc & orc. */
26d67362 1532GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
99e300ef 1533
54623277 1534/* xor & xor. */
99e300ef 1535static void gen_xor(DisasContext *ctx)
9a64fbe4 1536{
9a64fbe4 1537 /* Optimisation for "set to zero" case */
26d67362 1538 if (rS(ctx->opcode) != rB(ctx->opcode))
312179c4 1539 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1540 else
1541 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
76a66253 1542 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1543 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
9a64fbe4 1544}
99e300ef 1545
54623277 1546/* ori */
99e300ef 1547static void gen_ori(DisasContext *ctx)
79aceca5 1548{
76a66253 1549 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 1550
9a64fbe4 1551 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
9a64fbe4 1552 return;
76a66253 1553 }
26d67362 1554 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5 1555}
99e300ef 1556
54623277 1557/* oris */
99e300ef 1558static void gen_oris(DisasContext *ctx)
79aceca5 1559{
76a66253 1560 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 1561
9a64fbe4
FB
1562 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1563 /* NOP */
1564 return;
76a66253 1565 }
26d67362 1566 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
79aceca5 1567}
99e300ef 1568
54623277 1569/* xori */
99e300ef 1570static void gen_xori(DisasContext *ctx)
79aceca5 1571{
76a66253 1572 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
1573
1574 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1575 /* NOP */
1576 return;
1577 }
26d67362 1578 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5 1579}
99e300ef 1580
54623277 1581/* xoris */
99e300ef 1582static void gen_xoris(DisasContext *ctx)
79aceca5 1583{
76a66253 1584 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
1585
1586 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1587 /* NOP */
1588 return;
1589 }
26d67362 1590 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
79aceca5 1591}
99e300ef 1592
54623277 1593/* popcntb : PowerPC 2.03 specification */
99e300ef 1594static void gen_popcntb(DisasContext *ctx)
d9bce9d9 1595{
eaabeef2
DG
1596 gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1597}
1598
1599static void gen_popcntw(DisasContext *ctx)
1600{
1601 gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1602}
1603
d9bce9d9 1604#if defined(TARGET_PPC64)
eaabeef2
DG
1605/* popcntd: PowerPC 2.06 specification */
1606static void gen_popcntd(DisasContext *ctx)
1607{
1608 gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
d9bce9d9 1609}
eaabeef2 1610#endif
d9bce9d9 1611
725bcec2
AJ
1612/* prtyw: PowerPC 2.05 specification */
1613static void gen_prtyw(DisasContext *ctx)
1614{
1615 TCGv ra = cpu_gpr[rA(ctx->opcode)];
1616 TCGv rs = cpu_gpr[rS(ctx->opcode)];
1617 TCGv t0 = tcg_temp_new();
1618 tcg_gen_shri_tl(t0, rs, 16);
1619 tcg_gen_xor_tl(ra, rs, t0);
1620 tcg_gen_shri_tl(t0, ra, 8);
1621 tcg_gen_xor_tl(ra, ra, t0);
1622 tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL);
1623 tcg_temp_free(t0);
1624}
1625
1626#if defined(TARGET_PPC64)
1627/* prtyd: PowerPC 2.05 specification */
1628static void gen_prtyd(DisasContext *ctx)
1629{
1630 TCGv ra = cpu_gpr[rA(ctx->opcode)];
1631 TCGv rs = cpu_gpr[rS(ctx->opcode)];
1632 TCGv t0 = tcg_temp_new();
1633 tcg_gen_shri_tl(t0, rs, 32);
1634 tcg_gen_xor_tl(ra, rs, t0);
1635 tcg_gen_shri_tl(t0, ra, 16);
1636 tcg_gen_xor_tl(ra, ra, t0);
1637 tcg_gen_shri_tl(t0, ra, 8);
1638 tcg_gen_xor_tl(ra, ra, t0);
1639 tcg_gen_andi_tl(ra, ra, 1);
1640 tcg_temp_free(t0);
1641}
1642#endif
1643
86ba37ed
TM
1644#if defined(TARGET_PPC64)
1645/* bpermd */
1646static void gen_bpermd(DisasContext *ctx)
1647{
1648 gen_helper_bpermd(cpu_gpr[rA(ctx->opcode)],
1649 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1650}
1651#endif
1652
d9bce9d9
JM
1653#if defined(TARGET_PPC64)
1654/* extsw & extsw. */
26d67362 1655GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
99e300ef 1656
54623277 1657/* cntlzd */
99e300ef 1658static void gen_cntlzd(DisasContext *ctx)
26d67362 1659{
a7812ae4 1660 gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
26d67362
AJ
1661 if (unlikely(Rc(ctx->opcode) != 0))
1662 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1663}
d9bce9d9
JM
1664#endif
1665
79aceca5 1666/*** Integer rotate ***/
99e300ef 1667
54623277 1668/* rlwimi & rlwimi. */
99e300ef 1669static void gen_rlwimi(DisasContext *ctx)
79aceca5 1670{
63ae0915
RH
1671 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1672 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1673 uint32_t sh = SH(ctx->opcode);
1674 uint32_t mb = MB(ctx->opcode);
1675 uint32_t me = ME(ctx->opcode);
1676
1677 if (sh == (31-me) && mb <= me) {
1678 tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
d03ef511 1679 } else {
d03ef511 1680 target_ulong mask;
a7812ae4 1681 TCGv t1;
63ae0915 1682
76a66253 1683#if defined(TARGET_PPC64)
d03ef511
AJ
1684 mb += 32;
1685 me += 32;
76a66253 1686#endif
d03ef511 1687 mask = MASK(mb, me);
63ae0915 1688
a7812ae4 1689 t1 = tcg_temp_new();
2e11b15d
RH
1690 if (mask <= 0xffffffffu) {
1691 TCGv_i32 t0 = tcg_temp_new_i32();
1692 tcg_gen_trunc_tl_i32(t0, t_rs);
1693 tcg_gen_rotli_i32(t0, t0, sh);
1694 tcg_gen_extu_i32_tl(t1, t0);
1695 tcg_temp_free_i32(t0);
1696 } else {
1697#if defined(TARGET_PPC64)
1698 tcg_gen_deposit_i64(t1, t_rs, t_rs, 32, 32);
1699 tcg_gen_rotli_i64(t1, t1, sh);
1700#else
1701 g_assert_not_reached();
1702#endif
1703 }
63ae0915
RH
1704
1705 tcg_gen_andi_tl(t1, t1, mask);
1706 tcg_gen_andi_tl(t_ra, t_ra, ~mask);
1707 tcg_gen_or_tl(t_ra, t_ra, t1);
d03ef511
AJ
1708 tcg_temp_free(t1);
1709 }
63ae0915
RH
1710 if (unlikely(Rc(ctx->opcode) != 0)) {
1711 gen_set_Rc0(ctx, t_ra);
1712 }
79aceca5 1713}
99e300ef 1714
54623277 1715/* rlwinm & rlwinm. */
99e300ef 1716static void gen_rlwinm(DisasContext *ctx)
79aceca5 1717{
63ae0915
RH
1718 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1719 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1720 uint32_t sh = SH(ctx->opcode);
1721 uint32_t mb = MB(ctx->opcode);
1722 uint32_t me = ME(ctx->opcode);
1723
1724 if (mb == 0 && me == (31 - sh)) {
1725 tcg_gen_shli_tl(t_ra, t_rs, sh);
1726 tcg_gen_ext32u_tl(t_ra, t_ra);
1727 } else if (sh != 0 && me == 31 && sh == (32 - mb)) {
1728 tcg_gen_ext32u_tl(t_ra, t_rs);
1729 tcg_gen_shri_tl(t_ra, t_ra, mb);
d03ef511 1730 } else {
2e11b15d 1731 target_ulong mask;
76a66253 1732#if defined(TARGET_PPC64)
d03ef511
AJ
1733 mb += 32;
1734 me += 32;
76a66253 1735#endif
2e11b15d
RH
1736 mask = MASK(mb, me);
1737
820724d1 1738 if (mask <= 0xffffffffu) {
63ae0915 1739 TCGv_i32 t0 = tcg_temp_new_i32();
63ae0915
RH
1740 tcg_gen_trunc_tl_i32(t0, t_rs);
1741 tcg_gen_rotli_i32(t0, t0, sh);
2e11b15d 1742 tcg_gen_andi_i32(t0, t0, mask);
63ae0915
RH
1743 tcg_gen_extu_i32_tl(t_ra, t0);
1744 tcg_temp_free_i32(t0);
2e11b15d
RH
1745 } else {
1746#if defined(TARGET_PPC64)
1747 tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
1748 tcg_gen_rotli_i64(t_ra, t_ra, sh);
1749 tcg_gen_andi_i64(t_ra, t_ra, mask);
1750#else
1751 g_assert_not_reached();
1752#endif
63ae0915
RH
1753 }
1754 }
1755 if (unlikely(Rc(ctx->opcode) != 0)) {
1756 gen_set_Rc0(ctx, t_ra);
d03ef511 1757 }
79aceca5 1758}
99e300ef 1759
54623277 1760/* rlwnm & rlwnm. */
99e300ef 1761static void gen_rlwnm(DisasContext *ctx)
79aceca5 1762{
63ae0915
RH
1763 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1764 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1765 TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
1766 uint32_t mb = MB(ctx->opcode);
1767 uint32_t me = ME(ctx->opcode);
2e11b15d 1768 target_ulong mask;
57fca134 1769
54843a58 1770#if defined(TARGET_PPC64)
63ae0915
RH
1771 mb += 32;
1772 me += 32;
54843a58 1773#endif
2e11b15d
RH
1774 mask = MASK(mb, me);
1775
1776 if (mask <= 0xffffffffu) {
1777 TCGv_i32 t0 = tcg_temp_new_i32();
1778 TCGv_i32 t1 = tcg_temp_new_i32();
1779 tcg_gen_trunc_tl_i32(t0, t_rb);
1780 tcg_gen_trunc_tl_i32(t1, t_rs);
1781 tcg_gen_andi_i32(t0, t0, 0x1f);
1782 tcg_gen_rotl_i32(t1, t1, t0);
1783 tcg_gen_extu_i32_tl(t_ra, t1);
1784 tcg_temp_free_i32(t0);
1785 tcg_temp_free_i32(t1);
1786 } else {
1787#if defined(TARGET_PPC64)
1788 TCGv_i64 t0 = tcg_temp_new_i64();
1789 tcg_gen_andi_i64(t0, t_rb, 0x1f);
1790 tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
1791 tcg_gen_rotl_i64(t_ra, t_ra, t0);
1792 tcg_temp_free_i64(t0);
1793#else
1794 g_assert_not_reached();
1795#endif
1796 }
57fca134 1797
2e11b15d 1798 tcg_gen_andi_tl(t_ra, t_ra, mask);
63ae0915
RH
1799
1800 if (unlikely(Rc(ctx->opcode) != 0)) {
1801 gen_set_Rc0(ctx, t_ra);
79aceca5 1802 }
79aceca5
FB
1803}
1804
d9bce9d9
JM
1805#if defined(TARGET_PPC64)
1806#define GEN_PPC64_R2(name, opc1, opc2) \
e8eaa2c0 1807static void glue(gen_, name##0)(DisasContext *ctx) \
d9bce9d9
JM
1808{ \
1809 gen_##name(ctx, 0); \
1810} \
e8eaa2c0
BS
1811 \
1812static void glue(gen_, name##1)(DisasContext *ctx) \
d9bce9d9
JM
1813{ \
1814 gen_##name(ctx, 1); \
1815}
1816#define GEN_PPC64_R4(name, opc1, opc2) \
e8eaa2c0 1817static void glue(gen_, name##0)(DisasContext *ctx) \
d9bce9d9
JM
1818{ \
1819 gen_##name(ctx, 0, 0); \
1820} \
e8eaa2c0
BS
1821 \
1822static void glue(gen_, name##1)(DisasContext *ctx) \
d9bce9d9
JM
1823{ \
1824 gen_##name(ctx, 0, 1); \
1825} \
e8eaa2c0
BS
1826 \
1827static void glue(gen_, name##2)(DisasContext *ctx) \
d9bce9d9
JM
1828{ \
1829 gen_##name(ctx, 1, 0); \
1830} \
e8eaa2c0
BS
1831 \
1832static void glue(gen_, name##3)(DisasContext *ctx) \
d9bce9d9
JM
1833{ \
1834 gen_##name(ctx, 1, 1); \
1835}
51789c41 1836
a7b2c8b9 1837static void gen_rldinm(DisasContext *ctx, int mb, int me, int sh)
51789c41 1838{
a7b2c8b9
RH
1839 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1840 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1841
1842 if (sh != 0 && mb == 0 && me == (63 - sh)) {
1843 tcg_gen_shli_tl(t_ra, t_rs, sh);
1844 } else if (sh != 0 && me == 63 && sh == (64 - mb)) {
1845 tcg_gen_shri_tl(t_ra, t_rs, mb);
d03ef511 1846 } else {
a7b2c8b9
RH
1847 tcg_gen_rotli_tl(t_ra, t_rs, sh);
1848 tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
1849 }
1850 if (unlikely(Rc(ctx->opcode) != 0)) {
1851 gen_set_Rc0(ctx, t_ra);
51789c41 1852 }
51789c41 1853}
a7b2c8b9 1854
d9bce9d9 1855/* rldicl - rldicl. */
636aa200 1856static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
d9bce9d9 1857{
51789c41 1858 uint32_t sh, mb;
d9bce9d9 1859
9d53c753
JM
1860 sh = SH(ctx->opcode) | (shn << 5);
1861 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 1862 gen_rldinm(ctx, mb, 63, sh);
d9bce9d9 1863}
51789c41 1864GEN_PPC64_R4(rldicl, 0x1E, 0x00);
a7b2c8b9 1865
d9bce9d9 1866/* rldicr - rldicr. */
636aa200 1867static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
d9bce9d9 1868{
51789c41 1869 uint32_t sh, me;
d9bce9d9 1870
9d53c753
JM
1871 sh = SH(ctx->opcode) | (shn << 5);
1872 me = MB(ctx->opcode) | (men << 5);
51789c41 1873 gen_rldinm(ctx, 0, me, sh);
d9bce9d9 1874}
51789c41 1875GEN_PPC64_R4(rldicr, 0x1E, 0x02);
a7b2c8b9 1876
d9bce9d9 1877/* rldic - rldic. */
636aa200 1878static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
d9bce9d9 1879{
51789c41 1880 uint32_t sh, mb;
d9bce9d9 1881
9d53c753
JM
1882 sh = SH(ctx->opcode) | (shn << 5);
1883 mb = MB(ctx->opcode) | (mbn << 5);
51789c41
JM
1884 gen_rldinm(ctx, mb, 63 - sh, sh);
1885}
1886GEN_PPC64_R4(rldic, 0x1E, 0x04);
1887
a7b2c8b9 1888static void gen_rldnm(DisasContext *ctx, int mb, int me)
51789c41 1889{
a7b2c8b9
RH
1890 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1891 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1892 TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
54843a58 1893 TCGv t0;
d03ef511 1894
a7812ae4 1895 t0 = tcg_temp_new();
a7b2c8b9
RH
1896 tcg_gen_andi_tl(t0, t_rb, 0x3f);
1897 tcg_gen_rotl_tl(t_ra, t_rs, t0);
54843a58 1898 tcg_temp_free(t0);
a7b2c8b9
RH
1899
1900 tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
1901 if (unlikely(Rc(ctx->opcode) != 0)) {
1902 gen_set_Rc0(ctx, t_ra);
1903 }
d9bce9d9 1904}
51789c41 1905
d9bce9d9 1906/* rldcl - rldcl. */
636aa200 1907static inline void gen_rldcl(DisasContext *ctx, int mbn)
d9bce9d9 1908{
51789c41 1909 uint32_t mb;
d9bce9d9 1910
9d53c753 1911 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 1912 gen_rldnm(ctx, mb, 63);
d9bce9d9 1913}
36081602 1914GEN_PPC64_R2(rldcl, 0x1E, 0x08);
a7b2c8b9 1915
d9bce9d9 1916/* rldcr - rldcr. */
636aa200 1917static inline void gen_rldcr(DisasContext *ctx, int men)
d9bce9d9 1918{
51789c41 1919 uint32_t me;
d9bce9d9 1920
9d53c753 1921 me = MB(ctx->opcode) | (men << 5);
51789c41 1922 gen_rldnm(ctx, 0, me);
d9bce9d9 1923}
36081602 1924GEN_PPC64_R2(rldcr, 0x1E, 0x09);
a7b2c8b9 1925
d9bce9d9 1926/* rldimi - rldimi. */
a7b2c8b9 1927static void gen_rldimi(DisasContext *ctx, int mbn, int shn)
d9bce9d9 1928{
a7b2c8b9
RH
1929 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
1930 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
1931 uint32_t sh = SH(ctx->opcode) | (shn << 5);
1932 uint32_t mb = MB(ctx->opcode) | (mbn << 5);
1933 uint32_t me = 63 - sh;
d9bce9d9 1934
a7b2c8b9
RH
1935 if (mb <= me) {
1936 tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
d03ef511 1937 } else {
a7b2c8b9
RH
1938 target_ulong mask = MASK(mb, me);
1939 TCGv t1 = tcg_temp_new();
d03ef511 1940
a7b2c8b9
RH
1941 tcg_gen_rotli_tl(t1, t_rs, sh);
1942 tcg_gen_andi_tl(t1, t1, mask);
1943 tcg_gen_andi_tl(t_ra, t_ra, ~mask);
1944 tcg_gen_or_tl(t_ra, t_ra, t1);
d03ef511 1945 tcg_temp_free(t1);
51789c41 1946 }
a7b2c8b9
RH
1947 if (unlikely(Rc(ctx->opcode) != 0)) {
1948 gen_set_Rc0(ctx, t_ra);
1949 }
d9bce9d9 1950}
36081602 1951GEN_PPC64_R4(rldimi, 0x1E, 0x06);
d9bce9d9
JM
1952#endif
1953
79aceca5 1954/*** Integer shift ***/
99e300ef 1955
54623277 1956/* slw & slw. */
99e300ef 1957static void gen_slw(DisasContext *ctx)
26d67362 1958{
7fd6bf7d 1959 TCGv t0, t1;
26d67362 1960
7fd6bf7d
AJ
1961 t0 = tcg_temp_new();
1962 /* AND rS with a mask that is 0 when rB >= 0x20 */
1963#if defined(TARGET_PPC64)
1964 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1965 tcg_gen_sari_tl(t0, t0, 0x3f);
1966#else
1967 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1968 tcg_gen_sari_tl(t0, t0, 0x1f);
1969#endif
1970 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1971 t1 = tcg_temp_new();
1972 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1973 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1974 tcg_temp_free(t1);
fea0c503 1975 tcg_temp_free(t0);
7fd6bf7d 1976 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
26d67362
AJ
1977 if (unlikely(Rc(ctx->opcode) != 0))
1978 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1979}
99e300ef 1980
54623277 1981/* sraw & sraw. */
99e300ef 1982static void gen_sraw(DisasContext *ctx)
26d67362 1983{
d15f74fb 1984 gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
a7812ae4 1985 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1986 if (unlikely(Rc(ctx->opcode) != 0))
1987 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1988}
99e300ef 1989
54623277 1990/* srawi & srawi. */
99e300ef 1991static void gen_srawi(DisasContext *ctx)
79aceca5 1992{
26d67362 1993 int sh = SH(ctx->opcode);
ba4af3e4
RH
1994 TCGv dst = cpu_gpr[rA(ctx->opcode)];
1995 TCGv src = cpu_gpr[rS(ctx->opcode)];
1996 if (sh == 0) {
34a0fad1 1997 tcg_gen_ext32s_tl(dst, src);
da91a00f 1998 tcg_gen_movi_tl(cpu_ca, 0);
26d67362 1999 } else {
ba4af3e4
RH
2000 TCGv t0;
2001 tcg_gen_ext32s_tl(dst, src);
2002 tcg_gen_andi_tl(cpu_ca, dst, (1ULL << sh) - 1);
2003 t0 = tcg_temp_new();
2004 tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1);
2005 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
2006 tcg_temp_free(t0);
2007 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
2008 tcg_gen_sari_tl(dst, dst, sh);
2009 }
2010 if (unlikely(Rc(ctx->opcode) != 0)) {
2011 gen_set_Rc0(ctx, dst);
d9bce9d9 2012 }
79aceca5 2013}
99e300ef 2014
54623277 2015/* srw & srw. */
99e300ef 2016static void gen_srw(DisasContext *ctx)
26d67362 2017{
fea0c503 2018 TCGv t0, t1;
d9bce9d9 2019
7fd6bf7d
AJ
2020 t0 = tcg_temp_new();
2021 /* AND rS with a mask that is 0 when rB >= 0x20 */
2022#if defined(TARGET_PPC64)
2023 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
2024 tcg_gen_sari_tl(t0, t0, 0x3f);
2025#else
2026 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
2027 tcg_gen_sari_tl(t0, t0, 0x1f);
2028#endif
2029 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2030 tcg_gen_ext32u_tl(t0, t0);
a7812ae4 2031 t1 = tcg_temp_new();
7fd6bf7d
AJ
2032 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
2033 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
fea0c503 2034 tcg_temp_free(t1);
fea0c503 2035 tcg_temp_free(t0);
26d67362
AJ
2036 if (unlikely(Rc(ctx->opcode) != 0))
2037 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2038}
54623277 2039
d9bce9d9
JM
2040#if defined(TARGET_PPC64)
2041/* sld & sld. */
99e300ef 2042static void gen_sld(DisasContext *ctx)
26d67362 2043{
7fd6bf7d 2044 TCGv t0, t1;
26d67362 2045
7fd6bf7d
AJ
2046 t0 = tcg_temp_new();
2047 /* AND rS with a mask that is 0 when rB >= 0x40 */
2048 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
2049 tcg_gen_sari_tl(t0, t0, 0x3f);
2050 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2051 t1 = tcg_temp_new();
2052 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
2053 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2054 tcg_temp_free(t1);
fea0c503 2055 tcg_temp_free(t0);
26d67362
AJ
2056 if (unlikely(Rc(ctx->opcode) != 0))
2057 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2058}
99e300ef 2059
54623277 2060/* srad & srad. */
99e300ef 2061static void gen_srad(DisasContext *ctx)
26d67362 2062{
d15f74fb 2063 gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
a7812ae4 2064 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
2065 if (unlikely(Rc(ctx->opcode) != 0))
2066 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2067}
d9bce9d9 2068/* sradi & sradi. */
636aa200 2069static inline void gen_sradi(DisasContext *ctx, int n)
d9bce9d9 2070{
26d67362 2071 int sh = SH(ctx->opcode) + (n << 5);
ba4af3e4
RH
2072 TCGv dst = cpu_gpr[rA(ctx->opcode)];
2073 TCGv src = cpu_gpr[rS(ctx->opcode)];
2074 if (sh == 0) {
2075 tcg_gen_mov_tl(dst, src);
da91a00f 2076 tcg_gen_movi_tl(cpu_ca, 0);
26d67362 2077 } else {
ba4af3e4
RH
2078 TCGv t0;
2079 tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
2080 t0 = tcg_temp_new();
2081 tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1);
2082 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
2083 tcg_temp_free(t0);
2084 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
2085 tcg_gen_sari_tl(dst, src, sh);
2086 }
2087 if (unlikely(Rc(ctx->opcode) != 0)) {
2088 gen_set_Rc0(ctx, dst);
d9bce9d9 2089 }
d9bce9d9 2090}
e8eaa2c0
BS
2091
2092static void gen_sradi0(DisasContext *ctx)
d9bce9d9
JM
2093{
2094 gen_sradi(ctx, 0);
2095}
e8eaa2c0
BS
2096
2097static void gen_sradi1(DisasContext *ctx)
d9bce9d9
JM
2098{
2099 gen_sradi(ctx, 1);
2100}
99e300ef 2101
54623277 2102/* srd & srd. */
99e300ef 2103static void gen_srd(DisasContext *ctx)
26d67362 2104{
7fd6bf7d 2105 TCGv t0, t1;
26d67362 2106
7fd6bf7d
AJ
2107 t0 = tcg_temp_new();
2108 /* AND rS with a mask that is 0 when rB >= 0x40 */
2109 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
2110 tcg_gen_sari_tl(t0, t0, 0x3f);
2111 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2112 t1 = tcg_temp_new();
2113 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
2114 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2115 tcg_temp_free(t1);
fea0c503 2116 tcg_temp_free(t0);
26d67362
AJ
2117 if (unlikely(Rc(ctx->opcode) != 0))
2118 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2119}
d9bce9d9 2120#endif
79aceca5 2121
4814f2d1
TM
2122#if defined(TARGET_PPC64)
2123static void gen_set_cr1_from_fpscr(DisasContext *ctx)
2124{
2125 TCGv_i32 tmp = tcg_temp_new_i32();
2126 tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
2127 tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
2128 tcg_temp_free_i32(tmp);
2129}
2130#else
2131static void gen_set_cr1_from_fpscr(DisasContext *ctx)
2132{
2133 tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
2134}
2135#endif
2136
79aceca5 2137/*** Floating-Point arithmetic ***/
7c58044c 2138#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
99e300ef 2139static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2140{ \
76a66253 2141 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2142 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2143 return; \
2144 } \
eb44b959
AJ
2145 /* NIP cannot be restored if the memory exception comes from an helper */ \
2146 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2147 gen_reset_fpstatus(); \
8e703949
BS
2148 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2149 cpu_fpr[rA(ctx->opcode)], \
af12906f 2150 cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
4ecc3190 2151 if (isfloat) { \
8e703949
BS
2152 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2153 cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2154 } \
7d45556e
TM
2155 if (set_fprf) { \
2156 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
2157 } \
00e6fd3e
TM
2158 if (unlikely(Rc(ctx->opcode) != 0)) { \
2159 gen_set_cr1_from_fpscr(ctx); \
2160 } \
9a64fbe4
FB
2161}
2162
7c58044c
JM
2163#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
2164_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
2165_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
9a64fbe4 2166
7c58044c 2167#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
99e300ef 2168static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2169{ \
76a66253 2170 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2171 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2172 return; \
2173 } \
eb44b959
AJ
2174 /* NIP cannot be restored if the memory exception comes from an helper */ \
2175 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2176 gen_reset_fpstatus(); \
8e703949
BS
2177 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2178 cpu_fpr[rA(ctx->opcode)], \
af12906f 2179 cpu_fpr[rB(ctx->opcode)]); \
4ecc3190 2180 if (isfloat) { \
8e703949
BS
2181 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2182 cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2183 } \
7d45556e
TM
2184 if (set_fprf) { \
2185 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
2186 } \
00e6fd3e
TM
2187 if (unlikely(Rc(ctx->opcode) != 0)) { \
2188 gen_set_cr1_from_fpscr(ctx); \
2189 } \
9a64fbe4 2190}
7c58044c
JM
2191#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
2192_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2193_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
9a64fbe4 2194
7c58044c 2195#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
99e300ef 2196static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2197{ \
76a66253 2198 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2199 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2200 return; \
2201 } \
eb44b959
AJ
2202 /* NIP cannot be restored if the memory exception comes from an helper */ \
2203 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2204 gen_reset_fpstatus(); \
8e703949
BS
2205 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2206 cpu_fpr[rA(ctx->opcode)], \
2207 cpu_fpr[rC(ctx->opcode)]); \
4ecc3190 2208 if (isfloat) { \
8e703949
BS
2209 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2210 cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2211 } \
7d45556e
TM
2212 if (set_fprf) { \
2213 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
2214 } \
00e6fd3e
TM
2215 if (unlikely(Rc(ctx->opcode) != 0)) { \
2216 gen_set_cr1_from_fpscr(ctx); \
2217 } \
9a64fbe4 2218}
7c58044c
JM
2219#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
2220_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2221_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
9a64fbe4 2222
7c58044c 2223#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
99e300ef 2224static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2225{ \
76a66253 2226 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2227 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2228 return; \
2229 } \
eb44b959
AJ
2230 /* NIP cannot be restored if the memory exception comes from an helper */ \
2231 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2232 gen_reset_fpstatus(); \
8e703949
BS
2233 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2234 cpu_fpr[rB(ctx->opcode)]); \
7d45556e
TM
2235 if (set_fprf) { \
2236 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
2237 } \
00e6fd3e
TM
2238 if (unlikely(Rc(ctx->opcode) != 0)) { \
2239 gen_set_cr1_from_fpscr(ctx); \
2240 } \
79aceca5
FB
2241}
2242
7c58044c 2243#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
99e300ef 2244static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2245{ \
76a66253 2246 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2247 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2248 return; \
2249 } \
eb44b959
AJ
2250 /* NIP cannot be restored if the memory exception comes from an helper */ \
2251 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2252 gen_reset_fpstatus(); \
8e703949
BS
2253 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2254 cpu_fpr[rB(ctx->opcode)]); \
7d45556e
TM
2255 if (set_fprf) { \
2256 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
2257 } \
00e6fd3e
TM
2258 if (unlikely(Rc(ctx->opcode) != 0)) { \
2259 gen_set_cr1_from_fpscr(ctx); \
2260 } \
79aceca5
FB
2261}
2262
9a64fbe4 2263/* fadd - fadds */
7c58044c 2264GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
4ecc3190 2265/* fdiv - fdivs */
7c58044c 2266GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
4ecc3190 2267/* fmul - fmuls */
7c58044c 2268GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
79aceca5 2269
d7e4b87e 2270/* fre */
7c58044c 2271GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
d7e4b87e 2272
a750fc0b 2273/* fres */
7c58044c 2274GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
79aceca5 2275
a750fc0b 2276/* frsqrte */
7c58044c
JM
2277GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2278
2279/* frsqrtes */
99e300ef 2280static void gen_frsqrtes(DisasContext *ctx)
7c58044c 2281{
af12906f 2282 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2283 gen_exception(ctx, POWERPC_EXCP_FPU);
af12906f
AJ
2284 return;
2285 }
eb44b959
AJ
2286 /* NIP cannot be restored if the memory exception comes from an helper */
2287 gen_update_nip(ctx, ctx->nip - 4);
af12906f 2288 gen_reset_fpstatus();
8e703949
BS
2289 gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
2290 cpu_fpr[rB(ctx->opcode)]);
2291 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
2292 cpu_fpr[rD(ctx->opcode)]);
7d45556e 2293 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
00e6fd3e
TM
2294 if (unlikely(Rc(ctx->opcode) != 0)) {
2295 gen_set_cr1_from_fpscr(ctx);
2296 }
7c58044c 2297}
79aceca5 2298
a750fc0b 2299/* fsel */
7c58044c 2300_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
4ecc3190 2301/* fsub - fsubs */
7c58044c 2302GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
79aceca5 2303/* Optional: */
99e300ef 2304
54623277 2305/* fsqrt */
99e300ef 2306static void gen_fsqrt(DisasContext *ctx)
c7d344af 2307{
76a66253 2308 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2309 gen_exception(ctx, POWERPC_EXCP_FPU);
c7d344af
FB
2310 return;
2311 }
eb44b959
AJ
2312 /* NIP cannot be restored if the memory exception comes from an helper */
2313 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2314 gen_reset_fpstatus();
8e703949
BS
2315 gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
2316 cpu_fpr[rB(ctx->opcode)]);
7d45556e 2317 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
00e6fd3e
TM
2318 if (unlikely(Rc(ctx->opcode) != 0)) {
2319 gen_set_cr1_from_fpscr(ctx);
2320 }
c7d344af 2321}
79aceca5 2322
99e300ef 2323static void gen_fsqrts(DisasContext *ctx)
79aceca5 2324{
76a66253 2325 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2326 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2327 return;
2328 }
eb44b959
AJ
2329 /* NIP cannot be restored if the memory exception comes from an helper */
2330 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2331 gen_reset_fpstatus();
8e703949
BS
2332 gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
2333 cpu_fpr[rB(ctx->opcode)]);
2334 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
2335 cpu_fpr[rD(ctx->opcode)]);
7d45556e 2336 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
00e6fd3e
TM
2337 if (unlikely(Rc(ctx->opcode) != 0)) {
2338 gen_set_cr1_from_fpscr(ctx);
2339 }
79aceca5
FB
2340}
2341
2342/*** Floating-Point multiply-and-add ***/
4ecc3190 2343/* fmadd - fmadds */
7c58044c 2344GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
4ecc3190 2345/* fmsub - fmsubs */
7c58044c 2346GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
4ecc3190 2347/* fnmadd - fnmadds */
7c58044c 2348GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
4ecc3190 2349/* fnmsub - fnmsubs */
7c58044c 2350GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
79aceca5
FB
2351
2352/*** Floating-Point round & convert ***/
2353/* fctiw */
7c58044c 2354GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
fab7fe42
TM
2355/* fctiwu */
2356GEN_FLOAT_B(ctiwu, 0x0E, 0x04, 0, PPC2_FP_CVT_ISA206);
79aceca5 2357/* fctiwz */
7c58044c 2358GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
fab7fe42
TM
2359/* fctiwuz */
2360GEN_FLOAT_B(ctiwuz, 0x0F, 0x04, 0, PPC2_FP_CVT_ISA206);
79aceca5 2361/* frsp */
7c58044c 2362GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
426613db 2363/* fcfid */
4171853c 2364GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC2_FP_CVT_S64);
28288b48
TM
2365/* fcfids */
2366GEN_FLOAT_B(cfids, 0x0E, 0x1A, 0, PPC2_FP_CVT_ISA206);
2367/* fcfidu */
2368GEN_FLOAT_B(cfidu, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
2369/* fcfidus */
2370GEN_FLOAT_B(cfidus, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
426613db 2371/* fctid */
4171853c 2372GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC2_FP_CVT_S64);
fab7fe42
TM
2373/* fctidu */
2374GEN_FLOAT_B(ctidu, 0x0E, 0x1D, 0, PPC2_FP_CVT_ISA206);
426613db 2375/* fctidz */
4171853c 2376GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC2_FP_CVT_S64);
fab7fe42
TM
2377/* fctidu */
2378GEN_FLOAT_B(ctiduz, 0x0F, 0x1D, 0, PPC2_FP_CVT_ISA206);
79aceca5 2379
d7e4b87e 2380/* frin */
7c58044c 2381GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
d7e4b87e 2382/* friz */
7c58044c 2383GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
d7e4b87e 2384/* frip */
7c58044c 2385GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
d7e4b87e 2386/* frim */
7c58044c 2387GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
d7e4b87e 2388
da29cb7b
TM
2389static void gen_ftdiv(DisasContext *ctx)
2390{
2391 if (unlikely(!ctx->fpu_enabled)) {
2392 gen_exception(ctx, POWERPC_EXCP_FPU);
2393 return;
2394 }
2395 gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2396 cpu_fpr[rB(ctx->opcode)]);
2397}
2398
6d41d146
TM
2399static void gen_ftsqrt(DisasContext *ctx)
2400{
2401 if (unlikely(!ctx->fpu_enabled)) {
2402 gen_exception(ctx, POWERPC_EXCP_FPU);
2403 return;
2404 }
2405 gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2406}
2407
da29cb7b
TM
2408
2409
79aceca5 2410/*** Floating-Point compare ***/
99e300ef 2411
54623277 2412/* fcmpo */
99e300ef 2413static void gen_fcmpo(DisasContext *ctx)
79aceca5 2414{
330c483b 2415 TCGv_i32 crf;
76a66253 2416 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2417 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2418 return;
2419 }
eb44b959
AJ
2420 /* NIP cannot be restored if the memory exception comes from an helper */
2421 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2422 gen_reset_fpstatus();
9a819377 2423 crf = tcg_const_i32(crfD(ctx->opcode));
8e703949
BS
2424 gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
2425 cpu_fpr[rB(ctx->opcode)], crf);
330c483b 2426 tcg_temp_free_i32(crf);
8e703949 2427 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2428}
2429
2430/* fcmpu */
99e300ef 2431static void gen_fcmpu(DisasContext *ctx)
79aceca5 2432{
330c483b 2433 TCGv_i32 crf;
76a66253 2434 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2435 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2436 return;
2437 }
eb44b959
AJ
2438 /* NIP cannot be restored if the memory exception comes from an helper */
2439 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2440 gen_reset_fpstatus();
9a819377 2441 crf = tcg_const_i32(crfD(ctx->opcode));
8e703949
BS
2442 gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
2443 cpu_fpr[rB(ctx->opcode)], crf);
330c483b 2444 tcg_temp_free_i32(crf);
8e703949 2445 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2446}
2447
9a64fbe4
FB
2448/*** Floating-point move ***/
2449/* fabs */
7c58044c 2450/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
bf45a2e6
AJ
2451static void gen_fabs(DisasContext *ctx)
2452{
2453 if (unlikely(!ctx->fpu_enabled)) {
2454 gen_exception(ctx, POWERPC_EXCP_FPU);
2455 return;
2456 }
2457 tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2458 ~(1ULL << 63));
4814f2d1
TM
2459 if (unlikely(Rc(ctx->opcode))) {
2460 gen_set_cr1_from_fpscr(ctx);
2461 }
bf45a2e6 2462}
9a64fbe4
FB
2463
2464/* fmr - fmr. */
7c58044c 2465/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
99e300ef 2466static void gen_fmr(DisasContext *ctx)
9a64fbe4 2467{
76a66253 2468 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2469 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2470 return;
2471 }
af12906f 2472 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
4814f2d1
TM
2473 if (unlikely(Rc(ctx->opcode))) {
2474 gen_set_cr1_from_fpscr(ctx);
2475 }
9a64fbe4
FB
2476}
2477
2478/* fnabs */
7c58044c 2479/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
bf45a2e6
AJ
2480static void gen_fnabs(DisasContext *ctx)
2481{
2482 if (unlikely(!ctx->fpu_enabled)) {
2483 gen_exception(ctx, POWERPC_EXCP_FPU);
2484 return;
2485 }
2486 tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2487 1ULL << 63);
4814f2d1
TM
2488 if (unlikely(Rc(ctx->opcode))) {
2489 gen_set_cr1_from_fpscr(ctx);
2490 }
bf45a2e6
AJ
2491}
2492
9a64fbe4 2493/* fneg */
7c58044c 2494/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
bf45a2e6
AJ
2495static void gen_fneg(DisasContext *ctx)
2496{
2497 if (unlikely(!ctx->fpu_enabled)) {
2498 gen_exception(ctx, POWERPC_EXCP_FPU);
2499 return;
2500 }
2501 tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2502 1ULL << 63);
4814f2d1
TM
2503 if (unlikely(Rc(ctx->opcode))) {
2504 gen_set_cr1_from_fpscr(ctx);
2505 }
bf45a2e6 2506}
9a64fbe4 2507
f0332888
AJ
2508/* fcpsgn: PowerPC 2.05 specification */
2509/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
2510static void gen_fcpsgn(DisasContext *ctx)
2511{
2512 if (unlikely(!ctx->fpu_enabled)) {
2513 gen_exception(ctx, POWERPC_EXCP_FPU);
2514 return;
2515 }
2516 tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2517 cpu_fpr[rB(ctx->opcode)], 0, 63);
4814f2d1
TM
2518 if (unlikely(Rc(ctx->opcode))) {
2519 gen_set_cr1_from_fpscr(ctx);
2520 }
f0332888
AJ
2521}
2522
097ec5d8
TM
2523static void gen_fmrgew(DisasContext *ctx)
2524{
2525 TCGv_i64 b0;
2526 if (unlikely(!ctx->fpu_enabled)) {
2527 gen_exception(ctx, POWERPC_EXCP_FPU);
2528 return;
2529 }
2530 b0 = tcg_temp_new_i64();
2531 tcg_gen_shri_i64(b0, cpu_fpr[rB(ctx->opcode)], 32);
2532 tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2533 b0, 0, 32);
2534 tcg_temp_free_i64(b0);
2535}
2536
2537static void gen_fmrgow(DisasContext *ctx)
2538{
2539 if (unlikely(!ctx->fpu_enabled)) {
2540 gen_exception(ctx, POWERPC_EXCP_FPU);
2541 return;
2542 }
2543 tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)],
2544 cpu_fpr[rB(ctx->opcode)],
2545 cpu_fpr[rA(ctx->opcode)],
2546 32, 32);
2547}
2548
79aceca5 2549/*** Floating-Point status & ctrl register ***/
99e300ef 2550
54623277 2551/* mcrfs */
99e300ef 2552static void gen_mcrfs(DisasContext *ctx)
79aceca5 2553{
30304420 2554 TCGv tmp = tcg_temp_new();
d1277156
JC
2555 TCGv_i32 tmask;
2556 TCGv_i64 tnew_fpscr = tcg_temp_new_i64();
7c58044c 2557 int bfa;
d1277156
JC
2558 int nibble;
2559 int shift;
7c58044c 2560
76a66253 2561 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2562 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2563 return;
2564 }
d1277156
JC
2565 bfa = crfS(ctx->opcode);
2566 nibble = 7 - bfa;
2567 shift = 4 * nibble;
2568 tcg_gen_shri_tl(tmp, cpu_fpscr, shift);
30304420 2569 tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
e1571908 2570 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
d1277156
JC
2571 tcg_temp_free(tmp);
2572 tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr);
2573 /* Only the exception bits (including FX) should be cleared if read */
2574 tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr, ~((0xF << shift) & FP_EX_CLEAR_BITS));
2575 /* FEX and VX need to be updated, so don't set fpscr directly */
2576 tmask = tcg_const_i32(1 << nibble);
2577 gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask);
2578 tcg_temp_free_i32(tmask);
2579 tcg_temp_free_i64(tnew_fpscr);
79aceca5
FB
2580}
2581
2582/* mffs */
99e300ef 2583static void gen_mffs(DisasContext *ctx)
79aceca5 2584{
76a66253 2585 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2586 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2587 return;
2588 }
7c58044c 2589 gen_reset_fpstatus();
30304420 2590 tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
14ba79c7
TM
2591 if (unlikely(Rc(ctx->opcode))) {
2592 gen_set_cr1_from_fpscr(ctx);
2593 }
79aceca5
FB
2594}
2595
2596/* mtfsb0 */
99e300ef 2597static void gen_mtfsb0(DisasContext *ctx)
79aceca5 2598{
fb0eaffc 2599 uint8_t crb;
3b46e624 2600
76a66253 2601 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2602 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2603 return;
2604 }
6e35d524 2605 crb = 31 - crbD(ctx->opcode);
7c58044c 2606 gen_reset_fpstatus();
6e35d524 2607 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
eb44b959
AJ
2608 TCGv_i32 t0;
2609 /* NIP cannot be restored if the memory exception comes from an helper */
2610 gen_update_nip(ctx, ctx->nip - 4);
2611 t0 = tcg_const_i32(crb);
8e703949 2612 gen_helper_fpscr_clrbit(cpu_env, t0);
6e35d524
AJ
2613 tcg_temp_free_i32(t0);
2614 }
7c58044c 2615 if (unlikely(Rc(ctx->opcode) != 0)) {
30304420
DG
2616 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2617 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
7c58044c 2618 }
79aceca5
FB
2619}
2620
2621/* mtfsb1 */
99e300ef 2622static void gen_mtfsb1(DisasContext *ctx)
79aceca5 2623{
fb0eaffc 2624 uint8_t crb;
3b46e624 2625
76a66253 2626 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2627 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2628 return;
2629 }
6e35d524 2630 crb = 31 - crbD(ctx->opcode);
7c58044c
JM
2631 gen_reset_fpstatus();
2632 /* XXX: we pretend we can only do IEEE floating-point computations */
af12906f 2633 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
eb44b959
AJ
2634 TCGv_i32 t0;
2635 /* NIP cannot be restored if the memory exception comes from an helper */
2636 gen_update_nip(ctx, ctx->nip - 4);
2637 t0 = tcg_const_i32(crb);
8e703949 2638 gen_helper_fpscr_setbit(cpu_env, t0);
0f2f39c2 2639 tcg_temp_free_i32(t0);
af12906f 2640 }
7c58044c 2641 if (unlikely(Rc(ctx->opcode) != 0)) {
30304420
DG
2642 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2643 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
7c58044c
JM
2644 }
2645 /* We can raise a differed exception */
8e703949 2646 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2647}
2648
2649/* mtfsf */
99e300ef 2650static void gen_mtfsf(DisasContext *ctx)
79aceca5 2651{
0f2f39c2 2652 TCGv_i32 t0;
7d08d856 2653 int flm, l, w;
af12906f 2654
76a66253 2655 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2656 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2657 return;
2658 }
7d08d856
AJ
2659 flm = FPFLM(ctx->opcode);
2660 l = FPL(ctx->opcode);
2661 w = FPW(ctx->opcode);
2662 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
2663 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2664 return;
2665 }
eb44b959
AJ
2666 /* NIP cannot be restored if the memory exception comes from an helper */
2667 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2668 gen_reset_fpstatus();
7d08d856
AJ
2669 if (l) {
2670 t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
2671 } else {
2672 t0 = tcg_const_i32(flm << (w * 8));
2673 }
8e703949 2674 gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
0f2f39c2 2675 tcg_temp_free_i32(t0);
7c58044c 2676 if (unlikely(Rc(ctx->opcode) != 0)) {
30304420
DG
2677 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2678 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
7c58044c
JM
2679 }
2680 /* We can raise a differed exception */
8e703949 2681 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2682}
2683
2684/* mtfsfi */
99e300ef 2685static void gen_mtfsfi(DisasContext *ctx)
79aceca5 2686{
7d08d856 2687 int bf, sh, w;
0f2f39c2
AJ
2688 TCGv_i64 t0;
2689 TCGv_i32 t1;
7c58044c 2690
76a66253 2691 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2692 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2693 return;
2694 }
7d08d856
AJ
2695 w = FPW(ctx->opcode);
2696 bf = FPBF(ctx->opcode);
2697 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
2698 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2699 return;
2700 }
2701 sh = (8 * w) + 7 - bf;
eb44b959
AJ
2702 /* NIP cannot be restored if the memory exception comes from an helper */
2703 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2704 gen_reset_fpstatus();
7d08d856 2705 t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
af12906f 2706 t1 = tcg_const_i32(1 << sh);
8e703949 2707 gen_helper_store_fpscr(cpu_env, t0, t1);
0f2f39c2
AJ
2708 tcg_temp_free_i64(t0);
2709 tcg_temp_free_i32(t1);
7c58044c 2710 if (unlikely(Rc(ctx->opcode) != 0)) {
30304420
DG
2711 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2712 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
7c58044c
JM
2713 }
2714 /* We can raise a differed exception */
8e703949 2715 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2716}
2717
76a66253
JM
2718/*** Addressing modes ***/
2719/* Register indirect with immediate index : EA = (rA|0) + SIMM */
636aa200
BS
2720static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
2721 target_long maskl)
76a66253
JM
2722{
2723 target_long simm = SIMM(ctx->opcode);
2724
be147d08 2725 simm &= ~maskl;
76db3ba4 2726 if (rA(ctx->opcode) == 0) {
c791fe84
RH
2727 if (NARROW_MODE(ctx)) {
2728 simm = (uint32_t)simm;
2729 }
e2be8d8d 2730 tcg_gen_movi_tl(EA, simm);
76db3ba4 2731 } else if (likely(simm != 0)) {
e2be8d8d 2732 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
c791fe84 2733 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
2734 tcg_gen_ext32u_tl(EA, EA);
2735 }
76db3ba4 2736 } else {
c791fe84 2737 if (NARROW_MODE(ctx)) {
76db3ba4 2738 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
c791fe84
RH
2739 } else {
2740 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2741 }
76db3ba4 2742 }
76a66253
JM
2743}
2744
636aa200 2745static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
76a66253 2746{
76db3ba4 2747 if (rA(ctx->opcode) == 0) {
c791fe84 2748 if (NARROW_MODE(ctx)) {
76db3ba4 2749 tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
c791fe84
RH
2750 } else {
2751 tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2752 }
76db3ba4 2753 } else {
e2be8d8d 2754 tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
c791fe84 2755 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
2756 tcg_gen_ext32u_tl(EA, EA);
2757 }
76db3ba4 2758 }
76a66253
JM
2759}
2760
636aa200 2761static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
76a66253 2762{
76db3ba4 2763 if (rA(ctx->opcode) == 0) {
e2be8d8d 2764 tcg_gen_movi_tl(EA, 0);
c791fe84
RH
2765 } else if (NARROW_MODE(ctx)) {
2766 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
76db3ba4 2767 } else {
c791fe84 2768 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
76db3ba4
AJ
2769 }
2770}
2771
636aa200
BS
2772static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
2773 target_long val)
76db3ba4
AJ
2774{
2775 tcg_gen_addi_tl(ret, arg1, val);
c791fe84 2776 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
2777 tcg_gen_ext32u_tl(ret, ret);
2778 }
76a66253
JM
2779}
2780
636aa200 2781static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
cf360a32 2782{
42a268c2 2783 TCGLabel *l1 = gen_new_label();
cf360a32
AJ
2784 TCGv t0 = tcg_temp_new();
2785 TCGv_i32 t1, t2;
2786 /* NIP cannot be restored if the memory exception comes from an helper */
2787 gen_update_nip(ctx, ctx->nip - 4);
2788 tcg_gen_andi_tl(t0, EA, mask);
2789 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2790 t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2791 t2 = tcg_const_i32(0);
e5f17ac6 2792 gen_helper_raise_exception_err(cpu_env, t1, t2);
cf360a32
AJ
2793 tcg_temp_free_i32(t1);
2794 tcg_temp_free_i32(t2);
2795 gen_set_label(l1);
2796 tcg_temp_free(t0);
2797}
2798
7863667f 2799/*** Integer load ***/
636aa200 2800static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
76db3ba4
AJ
2801{
2802 tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2803}
2804
636aa200 2805static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
76db3ba4 2806{
e22c357b
DK
2807 TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
2808 tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753
AJ
2809}
2810
636aa200 2811static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2812{
e22c357b
DK
2813 TCGMemOp op = MO_SW | ctx->default_tcg_memop_mask;
2814 tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753
AJ
2815}
2816
636aa200 2817static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2818{
e22c357b
DK
2819 TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
2820 tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753
AJ
2821}
2822
f976b09e
AG
2823static void gen_qemu_ld32u_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
2824{
2825 TCGv tmp = tcg_temp_new();
2826 gen_qemu_ld32u(ctx, tmp, addr);
2827 tcg_gen_extu_tl_i64(val, tmp);
2828 tcg_temp_free(tmp);
2829}
2830
636aa200 2831static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2832{
e22c357b
DK
2833 TCGMemOp op = MO_SL | ctx->default_tcg_memop_mask;
2834 tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753
AJ
2835}
2836
cac7f0ba
TM
2837static void gen_qemu_ld32s_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
2838{
2839 TCGv tmp = tcg_temp_new();
2840 gen_qemu_ld32s(ctx, tmp, addr);
2841 tcg_gen_ext_tl_i64(val, tmp);
2842 tcg_temp_free(tmp);
2843}
2844
636aa200 2845static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
b61f2753 2846{
e22c357b
DK
2847 TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
2848 tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
b61f2753
AJ
2849}
2850
636aa200 2851static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2852{
76db3ba4 2853 tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
b61f2753
AJ
2854}
2855
636aa200 2856static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2857{
e22c357b
DK
2858 TCGMemOp op = MO_UW | ctx->default_tcg_memop_mask;
2859 tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753
AJ
2860}
2861
636aa200 2862static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2863{
e22c357b
DK
2864 TCGMemOp op = MO_UL | ctx->default_tcg_memop_mask;
2865 tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753
AJ
2866}
2867
f976b09e
AG
2868static void gen_qemu_st32_i64(DisasContext *ctx, TCGv_i64 val, TCGv addr)
2869{
2870 TCGv tmp = tcg_temp_new();
2871 tcg_gen_trunc_i64_tl(tmp, val);
2872 gen_qemu_st32(ctx, tmp, addr);
2873 tcg_temp_free(tmp);
2874}
2875
636aa200 2876static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
b61f2753 2877{
e22c357b
DK
2878 TCGMemOp op = MO_Q | ctx->default_tcg_memop_mask;
2879 tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
b61f2753
AJ
2880}
2881
0c8aacd4 2882#define GEN_LD(name, ldop, opc, type) \
99e300ef 2883static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 2884{ \
76db3ba4
AJ
2885 TCGv EA; \
2886 gen_set_access_type(ctx, ACCESS_INT); \
2887 EA = tcg_temp_new(); \
2888 gen_addr_imm_index(ctx, EA, 0); \
2889 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753 2890 tcg_temp_free(EA); \
79aceca5
FB
2891}
2892
0c8aacd4 2893#define GEN_LDU(name, ldop, opc, type) \
99e300ef 2894static void glue(gen_, name##u)(DisasContext *ctx) \
79aceca5 2895{ \
b61f2753 2896 TCGv EA; \
76a66253
JM
2897 if (unlikely(rA(ctx->opcode) == 0 || \
2898 rA(ctx->opcode) == rD(ctx->opcode))) { \
e06fcd75 2899 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2900 return; \
9a64fbe4 2901 } \
76db3ba4 2902 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2903 EA = tcg_temp_new(); \
9d53c753 2904 if (type == PPC_64B) \
76db3ba4 2905 gen_addr_imm_index(ctx, EA, 0x03); \
9d53c753 2906 else \
76db3ba4
AJ
2907 gen_addr_imm_index(ctx, EA, 0); \
2908 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753
AJ
2909 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2910 tcg_temp_free(EA); \
79aceca5
FB
2911}
2912
0c8aacd4 2913#define GEN_LDUX(name, ldop, opc2, opc3, type) \
99e300ef 2914static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 2915{ \
b61f2753 2916 TCGv EA; \
76a66253
JM
2917 if (unlikely(rA(ctx->opcode) == 0 || \
2918 rA(ctx->opcode) == rD(ctx->opcode))) { \
e06fcd75 2919 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2920 return; \
9a64fbe4 2921 } \
76db3ba4 2922 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2923 EA = tcg_temp_new(); \
76db3ba4
AJ
2924 gen_addr_reg_index(ctx, EA); \
2925 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753
AJ
2926 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2927 tcg_temp_free(EA); \
79aceca5
FB
2928}
2929
cd6e9320 2930#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
99e300ef 2931static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 2932{ \
76db3ba4
AJ
2933 TCGv EA; \
2934 gen_set_access_type(ctx, ACCESS_INT); \
2935 EA = tcg_temp_new(); \
2936 gen_addr_reg_index(ctx, EA); \
2937 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753 2938 tcg_temp_free(EA); \
79aceca5 2939}
cd6e9320
TH
2940#define GEN_LDX(name, ldop, opc2, opc3, type) \
2941 GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
79aceca5 2942
0c8aacd4
AJ
2943#define GEN_LDS(name, ldop, op, type) \
2944GEN_LD(name, ldop, op | 0x20, type); \
2945GEN_LDU(name, ldop, op | 0x21, type); \
2946GEN_LDUX(name, ldop, 0x17, op | 0x01, type); \
2947GEN_LDX(name, ldop, 0x17, op | 0x00, type)
79aceca5
FB
2948
2949/* lbz lbzu lbzux lbzx */
0c8aacd4 2950GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
79aceca5 2951/* lha lhau lhaux lhax */
0c8aacd4 2952GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
79aceca5 2953/* lhz lhzu lhzux lhzx */
0c8aacd4 2954GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
79aceca5 2955/* lwz lwzu lwzux lwzx */
0c8aacd4 2956GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
d9bce9d9 2957#if defined(TARGET_PPC64)
d9bce9d9 2958/* lwaux */
0c8aacd4 2959GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
d9bce9d9 2960/* lwax */
0c8aacd4 2961GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
d9bce9d9 2962/* ldux */
0c8aacd4 2963GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
d9bce9d9 2964/* ldx */
0c8aacd4 2965GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
99e300ef
BS
2966
2967static void gen_ld(DisasContext *ctx)
d9bce9d9 2968{
b61f2753 2969 TCGv EA;
d9bce9d9
JM
2970 if (Rc(ctx->opcode)) {
2971 if (unlikely(rA(ctx->opcode) == 0 ||
2972 rA(ctx->opcode) == rD(ctx->opcode))) {
e06fcd75 2973 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
d9bce9d9
JM
2974 return;
2975 }
2976 }
76db3ba4 2977 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 2978 EA = tcg_temp_new();
76db3ba4 2979 gen_addr_imm_index(ctx, EA, 0x03);
d9bce9d9
JM
2980 if (ctx->opcode & 0x02) {
2981 /* lwa (lwau is undefined) */
76db3ba4 2982 gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
d9bce9d9
JM
2983 } else {
2984 /* ld - ldu */
76db3ba4 2985 gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
d9bce9d9 2986 }
d9bce9d9 2987 if (Rc(ctx->opcode))
b61f2753
AJ
2988 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2989 tcg_temp_free(EA);
d9bce9d9 2990}
99e300ef 2991
54623277 2992/* lq */
99e300ef 2993static void gen_lq(DisasContext *ctx)
be147d08 2994{
be147d08 2995 int ra, rd;
b61f2753 2996 TCGv EA;
be147d08 2997
e0498daa
TM
2998 /* lq is a legal user mode instruction starting in ISA 2.07 */
2999 bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3000 bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3001
c47493f2 3002 if (!legal_in_user_mode && ctx->pr) {
9b2fadda 3003 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
3004 return;
3005 }
e0498daa
TM
3006
3007 if (!le_is_supported && ctx->le_mode) {
3008 gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
3009 return;
3010 }
3011
be147d08
JM
3012 ra = rA(ctx->opcode);
3013 rd = rD(ctx->opcode);
3014 if (unlikely((rd & 1) || rd == ra)) {
e06fcd75 3015 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
be147d08
JM
3016 return;
3017 }
e0498daa 3018
76db3ba4 3019 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 3020 EA = tcg_temp_new();
76db3ba4 3021 gen_addr_imm_index(ctx, EA, 0x0F);
e0498daa 3022
e22c357b
DK
3023 /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
3024 64-bit byteswap already. */
e0498daa
TM
3025 if (unlikely(ctx->le_mode)) {
3026 gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
3027 gen_addr_add(ctx, EA, EA, 8);
3028 gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
3029 } else {
3030 gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
3031 gen_addr_add(ctx, EA, EA, 8);
3032 gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
3033 }
b61f2753 3034 tcg_temp_free(EA);
be147d08 3035}
d9bce9d9 3036#endif
79aceca5
FB
3037
3038/*** Integer store ***/
0c8aacd4 3039#define GEN_ST(name, stop, opc, type) \
99e300ef 3040static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 3041{ \
76db3ba4
AJ
3042 TCGv EA; \
3043 gen_set_access_type(ctx, ACCESS_INT); \
3044 EA = tcg_temp_new(); \
3045 gen_addr_imm_index(ctx, EA, 0); \
3046 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753 3047 tcg_temp_free(EA); \
79aceca5
FB
3048}
3049
0c8aacd4 3050#define GEN_STU(name, stop, opc, type) \
99e300ef 3051static void glue(gen_, stop##u)(DisasContext *ctx) \
79aceca5 3052{ \
b61f2753 3053 TCGv EA; \
76a66253 3054 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3055 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3056 return; \
9a64fbe4 3057 } \
76db3ba4 3058 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 3059 EA = tcg_temp_new(); \
9d53c753 3060 if (type == PPC_64B) \
76db3ba4 3061 gen_addr_imm_index(ctx, EA, 0x03); \
9d53c753 3062 else \
76db3ba4
AJ
3063 gen_addr_imm_index(ctx, EA, 0); \
3064 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753
AJ
3065 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3066 tcg_temp_free(EA); \
79aceca5
FB
3067}
3068
0c8aacd4 3069#define GEN_STUX(name, stop, opc2, opc3, type) \
99e300ef 3070static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 3071{ \
b61f2753 3072 TCGv EA; \
76a66253 3073 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3074 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3075 return; \
9a64fbe4 3076 } \
76db3ba4 3077 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 3078 EA = tcg_temp_new(); \
76db3ba4
AJ
3079 gen_addr_reg_index(ctx, EA); \
3080 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753
AJ
3081 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3082 tcg_temp_free(EA); \
79aceca5
FB
3083}
3084
cd6e9320
TH
3085#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
3086static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 3087{ \
76db3ba4
AJ
3088 TCGv EA; \
3089 gen_set_access_type(ctx, ACCESS_INT); \
3090 EA = tcg_temp_new(); \
3091 gen_addr_reg_index(ctx, EA); \
3092 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753 3093 tcg_temp_free(EA); \
79aceca5 3094}
cd6e9320
TH
3095#define GEN_STX(name, stop, opc2, opc3, type) \
3096 GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
79aceca5 3097
0c8aacd4
AJ
3098#define GEN_STS(name, stop, op, type) \
3099GEN_ST(name, stop, op | 0x20, type); \
3100GEN_STU(name, stop, op | 0x21, type); \
3101GEN_STUX(name, stop, 0x17, op | 0x01, type); \
3102GEN_STX(name, stop, 0x17, op | 0x00, type)
79aceca5
FB
3103
3104/* stb stbu stbux stbx */
0c8aacd4 3105GEN_STS(stb, st8, 0x06, PPC_INTEGER);
79aceca5 3106/* sth sthu sthux sthx */
0c8aacd4 3107GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
79aceca5 3108/* stw stwu stwux stwx */
0c8aacd4 3109GEN_STS(stw, st32, 0x04, PPC_INTEGER);
d9bce9d9 3110#if defined(TARGET_PPC64)
0c8aacd4
AJ
3111GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
3112GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
99e300ef
BS
3113
3114static void gen_std(DisasContext *ctx)
d9bce9d9 3115{
be147d08 3116 int rs;
b61f2753 3117 TCGv EA;
be147d08
JM
3118
3119 rs = rS(ctx->opcode);
84cab1e2 3120 if ((ctx->opcode & 0x3) == 0x2) { /* stq */
84cab1e2
TM
3121 bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3122 bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
3123
dfdd3e43
BH
3124 if (!(ctx->insns_flags & PPC_64BX)) {
3125 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3126 }
3127
c47493f2 3128 if (!legal_in_user_mode && ctx->pr) {
9b2fadda 3129 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
3130 return;
3131 }
84cab1e2
TM
3132
3133 if (!le_is_supported && ctx->le_mode) {
3134 gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
d9bce9d9
JM
3135 return;
3136 }
84cab1e2
TM
3137
3138 if (unlikely(rs & 1)) {
3139 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
be147d08
JM
3140 return;
3141 }
76db3ba4 3142 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 3143 EA = tcg_temp_new();
76db3ba4 3144 gen_addr_imm_index(ctx, EA, 0x03);
84cab1e2 3145
e22c357b
DK
3146 /* We only need to swap high and low halves. gen_qemu_st64 does
3147 necessary 64-bit byteswap already. */
84cab1e2
TM
3148 if (unlikely(ctx->le_mode)) {
3149 gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
3150 gen_addr_add(ctx, EA, EA, 8);
3151 gen_qemu_st64(ctx, cpu_gpr[rs], EA);
3152 } else {
3153 gen_qemu_st64(ctx, cpu_gpr[rs], EA);
3154 gen_addr_add(ctx, EA, EA, 8);
3155 gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
3156 }
b61f2753 3157 tcg_temp_free(EA);
be147d08 3158 } else {
84cab1e2 3159 /* std / stdu*/
be147d08
JM
3160 if (Rc(ctx->opcode)) {
3161 if (unlikely(rA(ctx->opcode) == 0)) {
e06fcd75 3162 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
be147d08
JM
3163 return;
3164 }
3165 }
76db3ba4 3166 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 3167 EA = tcg_temp_new();
76db3ba4
AJ
3168 gen_addr_imm_index(ctx, EA, 0x03);
3169 gen_qemu_st64(ctx, cpu_gpr[rs], EA);
be147d08 3170 if (Rc(ctx->opcode))
b61f2753
AJ
3171 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
3172 tcg_temp_free(EA);
d9bce9d9 3173 }
d9bce9d9
JM
3174}
3175#endif
79aceca5 3176/*** Integer load and store with byte reverse ***/
e22c357b 3177
79aceca5 3178/* lhbrx */
86178a57 3179static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 3180{
e22c357b
DK
3181 TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3182 tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753 3183}
0c8aacd4 3184GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
b61f2753 3185
79aceca5 3186/* lwbrx */
86178a57 3187static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 3188{
e22c357b
DK
3189 TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3190 tcg_gen_qemu_ld_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753 3191}
0c8aacd4 3192GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
b61f2753 3193
cd6e9320
TH
3194#if defined(TARGET_PPC64)
3195/* ldbrx */
3196static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
3197{
e22c357b
DK
3198 TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3199 tcg_gen_qemu_ld_i64(arg1, arg2, ctx->mem_idx, op);
cd6e9320
TH
3200}
3201GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
3202#endif /* TARGET_PPC64 */
3203
79aceca5 3204/* sthbrx */
86178a57 3205static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 3206{
e22c357b
DK
3207 TCGMemOp op = MO_UW | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3208 tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753 3209}
0c8aacd4 3210GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
b61f2753 3211
79aceca5 3212/* stwbrx */
86178a57 3213static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 3214{
e22c357b
DK
3215 TCGMemOp op = MO_UL | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3216 tcg_gen_qemu_st_tl(arg1, arg2, ctx->mem_idx, op);
b61f2753 3217}
0c8aacd4 3218GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
79aceca5 3219
cd6e9320
TH
3220#if defined(TARGET_PPC64)
3221/* stdbrx */
3222static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
3223{
e22c357b
DK
3224 TCGMemOp op = MO_Q | (ctx->default_tcg_memop_mask ^ MO_BSWAP);
3225 tcg_gen_qemu_st_i64(arg1, arg2, ctx->mem_idx, op);
cd6e9320
TH
3226}
3227GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
3228#endif /* TARGET_PPC64 */
3229
79aceca5 3230/*** Integer load and store multiple ***/
99e300ef 3231
54623277 3232/* lmw */
99e300ef 3233static void gen_lmw(DisasContext *ctx)
79aceca5 3234{
76db3ba4
AJ
3235 TCGv t0;
3236 TCGv_i32 t1;
3237 gen_set_access_type(ctx, ACCESS_INT);
76a66253 3238 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3239 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3240 t0 = tcg_temp_new();
3241 t1 = tcg_const_i32(rD(ctx->opcode));
3242 gen_addr_imm_index(ctx, t0, 0);
2f5a189c 3243 gen_helper_lmw(cpu_env, t0, t1);
ff4a62cd
AJ
3244 tcg_temp_free(t0);
3245 tcg_temp_free_i32(t1);
79aceca5
FB
3246}
3247
3248/* stmw */
99e300ef 3249static void gen_stmw(DisasContext *ctx)
79aceca5 3250{
76db3ba4
AJ
3251 TCGv t0;
3252 TCGv_i32 t1;
3253 gen_set_access_type(ctx, ACCESS_INT);
76a66253 3254 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3255 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3256 t0 = tcg_temp_new();
3257 t1 = tcg_const_i32(rS(ctx->opcode));
3258 gen_addr_imm_index(ctx, t0, 0);
2f5a189c 3259 gen_helper_stmw(cpu_env, t0, t1);
ff4a62cd
AJ
3260 tcg_temp_free(t0);
3261 tcg_temp_free_i32(t1);
79aceca5
FB
3262}
3263
3264/*** Integer load and store strings ***/
54623277 3265
79aceca5 3266/* lswi */
3fc6c082 3267/* PowerPC32 specification says we must generate an exception if
9a64fbe4
FB
3268 * rA is in the range of registers to be loaded.
3269 * In an other hand, IBM says this is valid, but rA won't be loaded.
3270 * For now, I'll follow the spec...
3271 */
99e300ef 3272static void gen_lswi(DisasContext *ctx)
79aceca5 3273{
dfbc799d
AJ
3274 TCGv t0;
3275 TCGv_i32 t1, t2;
79aceca5
FB
3276 int nb = NB(ctx->opcode);
3277 int start = rD(ctx->opcode);
9a64fbe4 3278 int ra = rA(ctx->opcode);
79aceca5
FB
3279 int nr;
3280
3281 if (nb == 0)
3282 nb = 32;
afbee712
TH
3283 nr = (nb + 3) / 4;
3284 if (unlikely(lsw_reg_in_range(start, nr, ra))) {
e06fcd75 3285 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
9fddaa0c 3286 return;
297d8e62 3287 }
76db3ba4 3288 gen_set_access_type(ctx, ACCESS_INT);
8dd4983c 3289 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3290 gen_update_nip(ctx, ctx->nip - 4);
dfbc799d 3291 t0 = tcg_temp_new();
76db3ba4 3292 gen_addr_register(ctx, t0);
dfbc799d
AJ
3293 t1 = tcg_const_i32(nb);
3294 t2 = tcg_const_i32(start);
2f5a189c 3295 gen_helper_lsw(cpu_env, t0, t1, t2);
dfbc799d
AJ
3296 tcg_temp_free(t0);
3297 tcg_temp_free_i32(t1);
3298 tcg_temp_free_i32(t2);
79aceca5
FB
3299}
3300
3301/* lswx */
99e300ef 3302static void gen_lswx(DisasContext *ctx)
79aceca5 3303{
76db3ba4
AJ
3304 TCGv t0;
3305 TCGv_i32 t1, t2, t3;
3306 gen_set_access_type(ctx, ACCESS_INT);
76a66253 3307 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3308 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3309 t0 = tcg_temp_new();
3310 gen_addr_reg_index(ctx, t0);
3311 t1 = tcg_const_i32(rD(ctx->opcode));
3312 t2 = tcg_const_i32(rA(ctx->opcode));
3313 t3 = tcg_const_i32(rB(ctx->opcode));
2f5a189c 3314 gen_helper_lswx(cpu_env, t0, t1, t2, t3);
dfbc799d
AJ
3315 tcg_temp_free(t0);
3316 tcg_temp_free_i32(t1);
3317 tcg_temp_free_i32(t2);
3318 tcg_temp_free_i32(t3);
79aceca5
FB
3319}
3320
3321/* stswi */
99e300ef 3322static void gen_stswi(DisasContext *ctx)
79aceca5 3323{
76db3ba4
AJ
3324 TCGv t0;
3325 TCGv_i32 t1, t2;
4b3686fa 3326 int nb = NB(ctx->opcode);
76db3ba4 3327 gen_set_access_type(ctx, ACCESS_INT);
76a66253 3328 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3329 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3330 t0 = tcg_temp_new();
3331 gen_addr_register(ctx, t0);
4b3686fa
FB
3332 if (nb == 0)
3333 nb = 32;
dfbc799d 3334 t1 = tcg_const_i32(nb);
76db3ba4 3335 t2 = tcg_const_i32(rS(ctx->opcode));
2f5a189c 3336 gen_helper_stsw(cpu_env, t0, t1, t2);
dfbc799d
AJ
3337 tcg_temp_free(t0);
3338 tcg_temp_free_i32(t1);
3339 tcg_temp_free_i32(t2);
79aceca5
FB
3340}
3341
3342/* stswx */
99e300ef 3343static void gen_stswx(DisasContext *ctx)
79aceca5 3344{
76db3ba4
AJ
3345 TCGv t0;
3346 TCGv_i32 t1, t2;
3347 gen_set_access_type(ctx, ACCESS_INT);
8dd4983c 3348 /* NIP cannot be restored if the memory exception comes from an helper */
5fafdf24 3349 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3350 t0 = tcg_temp_new();
3351 gen_addr_reg_index(ctx, t0);
3352 t1 = tcg_temp_new_i32();
dfbc799d
AJ
3353 tcg_gen_trunc_tl_i32(t1, cpu_xer);
3354 tcg_gen_andi_i32(t1, t1, 0x7F);
76db3ba4 3355 t2 = tcg_const_i32(rS(ctx->opcode));
2f5a189c 3356 gen_helper_stsw(cpu_env, t0, t1, t2);
dfbc799d
AJ
3357 tcg_temp_free(t0);
3358 tcg_temp_free_i32(t1);
3359 tcg_temp_free_i32(t2);
79aceca5
FB
3360}
3361
3362/*** Memory synchronisation ***/
3363/* eieio */
99e300ef 3364static void gen_eieio(DisasContext *ctx)
79aceca5 3365{
79aceca5
FB
3366}
3367
c5a8d8f3 3368#if !defined(CONFIG_USER_ONLY)
cd0c6f47
BH
3369static inline void gen_check_tlb_flush(DisasContext *ctx)
3370{
c5a8d8f3
BH
3371 TCGv_i32 t;
3372 TCGLabel *l;
cd0c6f47 3373
c5a8d8f3
BH
3374 if (!ctx->lazy_tlb_flush) {
3375 return;
3376 }
3377 l = gen_new_label();
3378 t = tcg_temp_new_i32();
cd0c6f47
BH
3379 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
3380 tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, l);
3381 gen_helper_check_tlb_flush(cpu_env);
3382 gen_set_label(l);
3383 tcg_temp_free_i32(t);
3384}
3385#else
3386static inline void gen_check_tlb_flush(DisasContext *ctx) { }
3387#endif
3388
79aceca5 3389/* isync */
99e300ef 3390static void gen_isync(DisasContext *ctx)
79aceca5 3391{
cd0c6f47
BH
3392 /*
3393 * We need to check for a pending TLB flush. This can only happen in
3394 * kernel mode however so check MSR_PR
3395 */
3396 if (!ctx->pr) {
3397 gen_check_tlb_flush(ctx);
3398 }
e06fcd75 3399 gen_stop_exception(ctx);
79aceca5
FB
3400}
3401
5c77a786
TM
3402#define LARX(name, len, loadop) \
3403static void gen_##name(DisasContext *ctx) \
3404{ \
3405 TCGv t0; \
3406 TCGv gpr = cpu_gpr[rD(ctx->opcode)]; \
3407 gen_set_access_type(ctx, ACCESS_RES); \
3408 t0 = tcg_temp_local_new(); \
3409 gen_addr_reg_index(ctx, t0); \
3410 if ((len) > 1) { \
3411 gen_check_align(ctx, t0, (len)-1); \
3412 } \
3413 gen_qemu_##loadop(ctx, gpr, t0); \
3414 tcg_gen_mov_tl(cpu_reserve, t0); \
3415 tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val)); \
3416 tcg_temp_free(t0); \
79aceca5
FB
3417}
3418
5c77a786
TM
3419/* lwarx */
3420LARX(lbarx, 1, ld8u);
3421LARX(lharx, 2, ld16u);
3422LARX(lwarx, 4, ld32u);
3423
3424
4425265b 3425#if defined(CONFIG_USER_ONLY)
587c51f7
TM
3426static void gen_conditional_store(DisasContext *ctx, TCGv EA,
3427 int reg, int size)
4425265b
NF
3428{
3429 TCGv t0 = tcg_temp_new();
3430 uint32_t save_exception = ctx->exception;
3431
1328c2bf 3432 tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
4425265b 3433 tcg_gen_movi_tl(t0, (size << 5) | reg);
1328c2bf 3434 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
4425265b
NF
3435 tcg_temp_free(t0);
3436 gen_update_nip(ctx, ctx->nip-4);
3437 ctx->exception = POWERPC_EXCP_BRANCH;
3438 gen_exception(ctx, POWERPC_EXCP_STCX);
3439 ctx->exception = save_exception;
3440}
4425265b 3441#else
587c51f7
TM
3442static void gen_conditional_store(DisasContext *ctx, TCGv EA,
3443 int reg, int size)
3444{
42a268c2 3445 TCGLabel *l1;
4425265b 3446
587c51f7
TM
3447 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3448 l1 = gen_new_label();
3449 tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1);
3450 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3451#if defined(TARGET_PPC64)
3452 if (size == 8) {
3453 gen_qemu_st64(ctx, cpu_gpr[reg], EA);
3454 } else
3455#endif
3456 if (size == 4) {
3457 gen_qemu_st32(ctx, cpu_gpr[reg], EA);
3458 } else if (size == 2) {
3459 gen_qemu_st16(ctx, cpu_gpr[reg], EA);
27b95bfe
TM
3460#if defined(TARGET_PPC64)
3461 } else if (size == 16) {
3707cd62 3462 TCGv gpr1, gpr2 , EA8;
27b95bfe
TM
3463 if (unlikely(ctx->le_mode)) {
3464 gpr1 = cpu_gpr[reg+1];
3465 gpr2 = cpu_gpr[reg];
3466 } else {
3467 gpr1 = cpu_gpr[reg];
3468 gpr2 = cpu_gpr[reg+1];
3469 }
3470 gen_qemu_st64(ctx, gpr1, EA);
3707cd62
TM
3471 EA8 = tcg_temp_local_new();
3472 gen_addr_add(ctx, EA8, EA, 8);
3473 gen_qemu_st64(ctx, gpr2, EA8);
3474 tcg_temp_free(EA8);
27b95bfe 3475#endif
587c51f7
TM
3476 } else {
3477 gen_qemu_st8(ctx, cpu_gpr[reg], EA);
4425265b 3478 }
587c51f7
TM
3479 gen_set_label(l1);
3480 tcg_gen_movi_tl(cpu_reserve, -1);
3481}
4425265b 3482#endif
587c51f7
TM
3483
3484#define STCX(name, len) \
3485static void gen_##name(DisasContext *ctx) \
3486{ \
3487 TCGv t0; \
27b95bfe
TM
3488 if (unlikely((len == 16) && (rD(ctx->opcode) & 1))) { \
3489 gen_inval_exception(ctx, \
3490 POWERPC_EXCP_INVAL_INVAL); \
3491 return; \
3492 } \
587c51f7
TM
3493 gen_set_access_type(ctx, ACCESS_RES); \
3494 t0 = tcg_temp_local_new(); \
3495 gen_addr_reg_index(ctx, t0); \
3496 if (len > 1) { \
3497 gen_check_align(ctx, t0, (len)-1); \
3498 } \
3499 gen_conditional_store(ctx, t0, rS(ctx->opcode), len); \
3500 tcg_temp_free(t0); \
79aceca5
FB
3501}
3502
587c51f7
TM
3503STCX(stbcx_, 1);
3504STCX(sthcx_, 2);
3505STCX(stwcx_, 4);
3506
426613db 3507#if defined(TARGET_PPC64)
426613db 3508/* ldarx */
5c77a786 3509LARX(ldarx, 8, ld64);
426613db 3510
9c294d5a
TM
3511/* lqarx */
3512static void gen_lqarx(DisasContext *ctx)
3513{
3514 TCGv EA;
3515 int rd = rD(ctx->opcode);
3516 TCGv gpr1, gpr2;
3517
3518 if (unlikely((rd & 1) || (rd == rA(ctx->opcode)) ||
3519 (rd == rB(ctx->opcode)))) {
3520 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3521 return;
3522 }
3523
3524 gen_set_access_type(ctx, ACCESS_RES);
3525 EA = tcg_temp_local_new();
3526 gen_addr_reg_index(ctx, EA);
3527 gen_check_align(ctx, EA, 15);
3528 if (unlikely(ctx->le_mode)) {
3529 gpr1 = cpu_gpr[rd+1];
3530 gpr2 = cpu_gpr[rd];
3531 } else {
3532 gpr1 = cpu_gpr[rd];
3533 gpr2 = cpu_gpr[rd+1];
3534 }
3535 gen_qemu_ld64(ctx, gpr1, EA);
3536 tcg_gen_mov_tl(cpu_reserve, EA);
3537
3538 gen_addr_add(ctx, EA, EA, 8);
3539 gen_qemu_ld64(ctx, gpr2, EA);
3540
3541 tcg_gen_st_tl(gpr1, cpu_env, offsetof(CPUPPCState, reserve_val));
3542 tcg_gen_st_tl(gpr2, cpu_env, offsetof(CPUPPCState, reserve_val2));
3543
3544 tcg_temp_free(EA);
3545}
3546
426613db 3547/* stdcx. */
587c51f7 3548STCX(stdcx_, 8);
27b95bfe 3549STCX(stqcx_, 16);
426613db
JM
3550#endif /* defined(TARGET_PPC64) */
3551
79aceca5 3552/* sync */
99e300ef 3553static void gen_sync(DisasContext *ctx)
79aceca5 3554{
cd0c6f47
BH
3555 uint32_t l = (ctx->opcode >> 21) & 3;
3556
3557 /*
c5a8d8f3
BH
3558 * We may need to check for a pending TLB flush.
3559 *
3560 * We do this on ptesync (l == 2) on ppc64 and any sync pn ppc32.
3561 *
3562 * Additionally, this can only happen in kernel mode however so
3563 * check MSR_PR as well.
cd0c6f47 3564 */
c5a8d8f3 3565 if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
cd0c6f47
BH
3566 gen_check_tlb_flush(ctx);
3567 }
79aceca5
FB
3568}
3569
0db1b20e 3570/* wait */
99e300ef 3571static void gen_wait(DisasContext *ctx)
0db1b20e 3572{
35b5066e 3573 TCGv_i32 t0 = tcg_const_i32(1);
259186a7
AF
3574 tcg_gen_st_i32(t0, cpu_env,
3575 -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
931ff272 3576 tcg_temp_free_i32(t0);
0db1b20e 3577 /* Stop translation, as the CPU is supposed to sleep from now */
e06fcd75 3578 gen_exception_err(ctx, EXCP_HLT, 1);
0db1b20e
JM
3579}
3580
79aceca5 3581/*** Floating-point load ***/
a0d7d5a7 3582#define GEN_LDF(name, ldop, opc, type) \
99e300ef 3583static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 3584{ \
a0d7d5a7 3585 TCGv EA; \
76a66253 3586 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3587 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3588 return; \
3589 } \
76db3ba4 3590 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3591 EA = tcg_temp_new(); \
76db3ba4
AJ
3592 gen_addr_imm_index(ctx, EA, 0); \
3593 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7 3594 tcg_temp_free(EA); \
79aceca5
FB
3595}
3596
a0d7d5a7 3597#define GEN_LDUF(name, ldop, opc, type) \
99e300ef 3598static void glue(gen_, name##u)(DisasContext *ctx) \
79aceca5 3599{ \
a0d7d5a7 3600 TCGv EA; \
76a66253 3601 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3602 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3603 return; \
3604 } \
76a66253 3605 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3606 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3607 return; \
9a64fbe4 3608 } \
76db3ba4 3609 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3610 EA = tcg_temp_new(); \
76db3ba4
AJ
3611 gen_addr_imm_index(ctx, EA, 0); \
3612 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7
AJ
3613 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3614 tcg_temp_free(EA); \
79aceca5
FB
3615}
3616
a0d7d5a7 3617#define GEN_LDUXF(name, ldop, opc, type) \
99e300ef 3618static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 3619{ \
a0d7d5a7 3620 TCGv EA; \
76a66253 3621 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3622 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3623 return; \
3624 } \
76a66253 3625 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3626 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3627 return; \
9a64fbe4 3628 } \
76db3ba4 3629 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3630 EA = tcg_temp_new(); \
76db3ba4
AJ
3631 gen_addr_reg_index(ctx, EA); \
3632 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7
AJ
3633 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3634 tcg_temp_free(EA); \
79aceca5
FB
3635}
3636
a0d7d5a7 3637#define GEN_LDXF(name, ldop, opc2, opc3, type) \
99e300ef 3638static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 3639{ \
a0d7d5a7 3640 TCGv EA; \
76a66253 3641 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3642 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3643 return; \
3644 } \
76db3ba4 3645 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3646 EA = tcg_temp_new(); \
76db3ba4
AJ
3647 gen_addr_reg_index(ctx, EA); \
3648 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7 3649 tcg_temp_free(EA); \
79aceca5
FB
3650}
3651
a0d7d5a7
AJ
3652#define GEN_LDFS(name, ldop, op, type) \
3653GEN_LDF(name, ldop, op | 0x20, type); \
3654GEN_LDUF(name, ldop, op | 0x21, type); \
3655GEN_LDUXF(name, ldop, op | 0x01, type); \
3656GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3657
636aa200 3658static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
a0d7d5a7
AJ
3659{
3660 TCGv t0 = tcg_temp_new();
3661 TCGv_i32 t1 = tcg_temp_new_i32();
76db3ba4 3662 gen_qemu_ld32u(ctx, t0, arg2);
a0d7d5a7
AJ
3663 tcg_gen_trunc_tl_i32(t1, t0);
3664 tcg_temp_free(t0);
8e703949 3665 gen_helper_float32_to_float64(arg1, cpu_env, t1);
a0d7d5a7
AJ
3666 tcg_temp_free_i32(t1);
3667}
79aceca5 3668
a0d7d5a7
AJ
3669 /* lfd lfdu lfdux lfdx */
3670GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3671 /* lfs lfsu lfsux lfsx */
3672GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
79aceca5 3673
05050ee8
AJ
3674/* lfdp */
3675static void gen_lfdp(DisasContext *ctx)
3676{
3677 TCGv EA;
3678 if (unlikely(!ctx->fpu_enabled)) {
3679 gen_exception(ctx, POWERPC_EXCP_FPU);
3680 return;
3681 }
3682 gen_set_access_type(ctx, ACCESS_FLOAT);
3683 EA = tcg_temp_new();
e22c357b
DK
3684 gen_addr_imm_index(ctx, EA, 0);
3685 /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
3686 64-bit byteswap already. */
05050ee8
AJ
3687 if (unlikely(ctx->le_mode)) {
3688 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3689 tcg_gen_addi_tl(EA, EA, 8);
3690 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3691 } else {
3692 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3693 tcg_gen_addi_tl(EA, EA, 8);
3694 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3695 }
3696 tcg_temp_free(EA);
3697}
3698
3699/* lfdpx */
3700static void gen_lfdpx(DisasContext *ctx)
3701{
3702 TCGv EA;
3703 if (unlikely(!ctx->fpu_enabled)) {
3704 gen_exception(ctx, POWERPC_EXCP_FPU);
3705 return;
3706 }
3707 gen_set_access_type(ctx, ACCESS_FLOAT);
3708 EA = tcg_temp_new();
3709 gen_addr_reg_index(ctx, EA);
e22c357b
DK
3710 /* We only need to swap high and low halves. gen_qemu_ld64 does necessary
3711 64-bit byteswap already. */
05050ee8
AJ
3712 if (unlikely(ctx->le_mode)) {
3713 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3714 tcg_gen_addi_tl(EA, EA, 8);
3715 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3716 } else {
3717 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3718 tcg_gen_addi_tl(EA, EA, 8);
3719 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3720 }
3721 tcg_temp_free(EA);
3722}
3723
199f830d
AJ
3724/* lfiwax */
3725static void gen_lfiwax(DisasContext *ctx)
3726{
3727 TCGv EA;
3728 TCGv t0;
3729 if (unlikely(!ctx->fpu_enabled)) {
3730 gen_exception(ctx, POWERPC_EXCP_FPU);
3731 return;
3732 }
3733 gen_set_access_type(ctx, ACCESS_FLOAT);
3734 EA = tcg_temp_new();
3735 t0 = tcg_temp_new();
3736 gen_addr_reg_index(ctx, EA);
909eedb7 3737 gen_qemu_ld32s(ctx, t0, EA);
199f830d 3738 tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
199f830d
AJ
3739 tcg_temp_free(EA);
3740 tcg_temp_free(t0);
3741}
3742
66c3e328
TM
3743/* lfiwzx */
3744static void gen_lfiwzx(DisasContext *ctx)
3745{
3746 TCGv EA;
3747 if (unlikely(!ctx->fpu_enabled)) {
3748 gen_exception(ctx, POWERPC_EXCP_FPU);
3749 return;
3750 }
3751 gen_set_access_type(ctx, ACCESS_FLOAT);
3752 EA = tcg_temp_new();
3753 gen_addr_reg_index(ctx, EA);
3754 gen_qemu_ld32u_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3755 tcg_temp_free(EA);
3756}
79aceca5 3757/*** Floating-point store ***/
a0d7d5a7 3758#define GEN_STF(name, stop, opc, type) \
99e300ef 3759static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 3760{ \
a0d7d5a7 3761 TCGv EA; \
76a66253 3762 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3763 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3764 return; \
3765 } \
76db3ba4 3766 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3767 EA = tcg_temp_new(); \
76db3ba4
AJ
3768 gen_addr_imm_index(ctx, EA, 0); \
3769 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7 3770 tcg_temp_free(EA); \
79aceca5
FB
3771}
3772
a0d7d5a7 3773#define GEN_STUF(name, stop, opc, type) \
99e300ef 3774static void glue(gen_, name##u)(DisasContext *ctx) \
79aceca5 3775{ \
a0d7d5a7 3776 TCGv EA; \
76a66253 3777 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3778 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3779 return; \
3780 } \
76a66253 3781 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3782 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3783 return; \
9a64fbe4 3784 } \
76db3ba4 3785 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3786 EA = tcg_temp_new(); \
76db3ba4
AJ
3787 gen_addr_imm_index(ctx, EA, 0); \
3788 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7
AJ
3789 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3790 tcg_temp_free(EA); \
79aceca5
FB
3791}
3792
a0d7d5a7 3793#define GEN_STUXF(name, stop, opc, type) \
99e300ef 3794static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 3795{ \
a0d7d5a7 3796 TCGv EA; \
76a66253 3797 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3798 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3799 return; \
3800 } \
76a66253 3801 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3802 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3803 return; \
9a64fbe4 3804 } \
76db3ba4 3805 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3806 EA = tcg_temp_new(); \
76db3ba4
AJ
3807 gen_addr_reg_index(ctx, EA); \
3808 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7
AJ
3809 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3810 tcg_temp_free(EA); \
79aceca5
FB
3811}
3812
a0d7d5a7 3813#define GEN_STXF(name, stop, opc2, opc3, type) \
99e300ef 3814static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 3815{ \
a0d7d5a7 3816 TCGv EA; \
76a66253 3817 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3818 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3819 return; \
3820 } \
76db3ba4 3821 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3822 EA = tcg_temp_new(); \
76db3ba4
AJ
3823 gen_addr_reg_index(ctx, EA); \
3824 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7 3825 tcg_temp_free(EA); \
79aceca5
FB
3826}
3827
a0d7d5a7
AJ
3828#define GEN_STFS(name, stop, op, type) \
3829GEN_STF(name, stop, op | 0x20, type); \
3830GEN_STUF(name, stop, op | 0x21, type); \
3831GEN_STUXF(name, stop, op | 0x01, type); \
3832GEN_STXF(name, stop, 0x17, op | 0x00, type)
3833
636aa200 3834static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
a0d7d5a7
AJ
3835{
3836 TCGv_i32 t0 = tcg_temp_new_i32();
3837 TCGv t1 = tcg_temp_new();
8e703949 3838 gen_helper_float64_to_float32(t0, cpu_env, arg1);
a0d7d5a7
AJ
3839 tcg_gen_extu_i32_tl(t1, t0);
3840 tcg_temp_free_i32(t0);
76db3ba4 3841 gen_qemu_st32(ctx, t1, arg2);
a0d7d5a7
AJ
3842 tcg_temp_free(t1);
3843}
79aceca5
FB
3844
3845/* stfd stfdu stfdux stfdx */
a0d7d5a7 3846GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
79aceca5 3847/* stfs stfsu stfsux stfsx */
a0d7d5a7 3848GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
79aceca5 3849
44bc0c4d
AJ
3850/* stfdp */
3851static void gen_stfdp(DisasContext *ctx)
3852{
3853 TCGv EA;
3854 if (unlikely(!ctx->fpu_enabled)) {
3855 gen_exception(ctx, POWERPC_EXCP_FPU);
3856 return;
3857 }
3858 gen_set_access_type(ctx, ACCESS_FLOAT);
3859 EA = tcg_temp_new();
e22c357b
DK
3860 gen_addr_imm_index(ctx, EA, 0);
3861 /* We only need to swap high and low halves. gen_qemu_st64 does necessary
3862 64-bit byteswap already. */
44bc0c4d
AJ
3863 if (unlikely(ctx->le_mode)) {
3864 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3865 tcg_gen_addi_tl(EA, EA, 8);
3866 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3867 } else {
3868 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3869 tcg_gen_addi_tl(EA, EA, 8);
3870 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3871 }
3872 tcg_temp_free(EA);
3873}
3874
3875/* stfdpx */
3876static void gen_stfdpx(DisasContext *ctx)
3877{
3878 TCGv EA;
3879 if (unlikely(!ctx->fpu_enabled)) {
3880 gen_exception(ctx, POWERPC_EXCP_FPU);
3881 return;
3882 }
3883 gen_set_access_type(ctx, ACCESS_FLOAT);
3884 EA = tcg_temp_new();
3885 gen_addr_reg_index(ctx, EA);
e22c357b
DK
3886 /* We only need to swap high and low halves. gen_qemu_st64 does necessary
3887 64-bit byteswap already. */
44bc0c4d
AJ
3888 if (unlikely(ctx->le_mode)) {
3889 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3890 tcg_gen_addi_tl(EA, EA, 8);
3891 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3892 } else {
3893 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3894 tcg_gen_addi_tl(EA, EA, 8);
3895 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3896 }
3897 tcg_temp_free(EA);
3898}
3899
79aceca5 3900/* Optional: */
636aa200 3901static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
a0d7d5a7
AJ
3902{
3903 TCGv t0 = tcg_temp_new();
3904 tcg_gen_trunc_i64_tl(t0, arg1),
76db3ba4 3905 gen_qemu_st32(ctx, t0, arg2);
a0d7d5a7
AJ
3906 tcg_temp_free(t0);
3907}
79aceca5 3908/* stfiwx */
a0d7d5a7 3909GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
79aceca5 3910
697ab892
DG
3911static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
3912{
3913#if defined(TARGET_PPC64)
3914 if (ctx->has_cfar)
3915 tcg_gen_movi_tl(cpu_cfar, nip);
3916#endif
3917}
3918
90aa39a1
SF
3919static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
3920{
3921 if (unlikely(ctx->singlestep_enabled)) {
3922 return false;
3923 }
3924
3925#ifndef CONFIG_USER_ONLY
3926 return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
3927#else
3928 return true;
3929#endif
3930}
3931
79aceca5 3932/*** Branch ***/
636aa200 3933static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c1942362 3934{
e0c8f9ce 3935 if (NARROW_MODE(ctx)) {
a2ffb812 3936 dest = (uint32_t) dest;
e0c8f9ce 3937 }
90aa39a1 3938 if (use_goto_tb(ctx, dest)) {
57fec1fe 3939 tcg_gen_goto_tb(n);
a2ffb812 3940 tcg_gen_movi_tl(cpu_nip, dest & ~3);
90aa39a1 3941 tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
c1942362 3942 } else {
a2ffb812 3943 tcg_gen_movi_tl(cpu_nip, dest & ~3);
8cbcb4fa
AJ
3944 if (unlikely(ctx->singlestep_enabled)) {
3945 if ((ctx->singlestep_enabled &
bdc4e053 3946 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
f0cc4aa8
JG
3947 (ctx->exception == POWERPC_EXCP_BRANCH ||
3948 ctx->exception == POWERPC_EXCP_TRACE)) {
8cbcb4fa
AJ
3949 target_ulong tmp = ctx->nip;
3950 ctx->nip = dest;
e06fcd75 3951 gen_exception(ctx, POWERPC_EXCP_TRACE);
8cbcb4fa
AJ
3952 ctx->nip = tmp;
3953 }
3954 if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
e06fcd75 3955 gen_debug_exception(ctx);
8cbcb4fa
AJ
3956 }
3957 }
57fec1fe 3958 tcg_gen_exit_tb(0);
c1942362 3959 }
c53be334
FB
3960}
3961
636aa200 3962static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
e1833e1f 3963{
e0c8f9ce
RH
3964 if (NARROW_MODE(ctx)) {
3965 nip = (uint32_t)nip;
3966 }
3967 tcg_gen_movi_tl(cpu_lr, nip);
e1833e1f
JM
3968}
3969
79aceca5 3970/* b ba bl bla */
99e300ef 3971static void gen_b(DisasContext *ctx)
79aceca5 3972{
76a66253 3973 target_ulong li, target;
38a64f9d 3974
8cbcb4fa 3975 ctx->exception = POWERPC_EXCP_BRANCH;
38a64f9d 3976 /* sign extend LI */
e0c8f9ce
RH
3977 li = LI(ctx->opcode);
3978 li = (li ^ 0x02000000) - 0x02000000;
3979 if (likely(AA(ctx->opcode) == 0)) {
046d6672 3980 target = ctx->nip + li - 4;
e0c8f9ce 3981 } else {
9a64fbe4 3982 target = li;
e0c8f9ce
RH
3983 }
3984 if (LK(ctx->opcode)) {
e1833e1f 3985 gen_setlr(ctx, ctx->nip);
e0c8f9ce 3986 }
697ab892 3987 gen_update_cfar(ctx, ctx->nip);
c1942362 3988 gen_goto_tb(ctx, 0, target);
79aceca5
FB
3989}
3990
e98a6e40
FB
3991#define BCOND_IM 0
3992#define BCOND_LR 1
3993#define BCOND_CTR 2
52a4984d 3994#define BCOND_TAR 3
e98a6e40 3995
636aa200 3996static inline void gen_bcond(DisasContext *ctx, int type)
d9bce9d9 3997{
d9bce9d9 3998 uint32_t bo = BO(ctx->opcode);
42a268c2 3999 TCGLabel *l1;
a2ffb812 4000 TCGv target;
e98a6e40 4001
8cbcb4fa 4002 ctx->exception = POWERPC_EXCP_BRANCH;
52a4984d 4003 if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
a7812ae4 4004 target = tcg_temp_local_new();
a2ffb812
AJ
4005 if (type == BCOND_CTR)
4006 tcg_gen_mov_tl(target, cpu_ctr);
52a4984d
TM
4007 else if (type == BCOND_TAR)
4008 gen_load_spr(target, SPR_TAR);
a2ffb812
AJ
4009 else
4010 tcg_gen_mov_tl(target, cpu_lr);
d2e9fd8f 4011 } else {
4012 TCGV_UNUSED(target);
e98a6e40 4013 }
e1833e1f
JM
4014 if (LK(ctx->opcode))
4015 gen_setlr(ctx, ctx->nip);
a2ffb812
AJ
4016 l1 = gen_new_label();
4017 if ((bo & 0x4) == 0) {
4018 /* Decrement and test CTR */
a7812ae4 4019 TCGv temp = tcg_temp_new();
a2ffb812 4020 if (unlikely(type == BCOND_CTR)) {
e06fcd75 4021 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
a2ffb812
AJ
4022 return;
4023 }
4024 tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
e0c8f9ce 4025 if (NARROW_MODE(ctx)) {
a2ffb812 4026 tcg_gen_ext32u_tl(temp, cpu_ctr);
e0c8f9ce 4027 } else {
a2ffb812 4028 tcg_gen_mov_tl(temp, cpu_ctr);
e0c8f9ce 4029 }
a2ffb812
AJ
4030 if (bo & 0x2) {
4031 tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
4032 } else {
4033 tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
e98a6e40 4034 }
a7812ae4 4035 tcg_temp_free(temp);
a2ffb812
AJ
4036 }
4037 if ((bo & 0x10) == 0) {
4038 /* Test CR */
4039 uint32_t bi = BI(ctx->opcode);
8f9fb7ac 4040 uint32_t mask = 0x08 >> (bi & 0x03);
a7812ae4 4041 TCGv_i32 temp = tcg_temp_new_i32();
a2ffb812 4042
d9bce9d9 4043 if (bo & 0x8) {
a2ffb812
AJ
4044 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
4045 tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
d9bce9d9 4046 } else {
a2ffb812
AJ
4047 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
4048 tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
d9bce9d9 4049 }
a7812ae4 4050 tcg_temp_free_i32(temp);
d9bce9d9 4051 }
697ab892 4052 gen_update_cfar(ctx, ctx->nip);
e98a6e40 4053 if (type == BCOND_IM) {
a2ffb812
AJ
4054 target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
4055 if (likely(AA(ctx->opcode) == 0)) {
4056 gen_goto_tb(ctx, 0, ctx->nip + li - 4);
4057 } else {
4058 gen_goto_tb(ctx, 0, li);
4059 }
c53be334 4060 gen_set_label(l1);
c1942362 4061 gen_goto_tb(ctx, 1, ctx->nip);
e98a6e40 4062 } else {
e0c8f9ce 4063 if (NARROW_MODE(ctx)) {
a2ffb812 4064 tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
e0c8f9ce 4065 } else {
a2ffb812 4066 tcg_gen_andi_tl(cpu_nip, target, ~3);
e0c8f9ce 4067 }
a2ffb812
AJ
4068 tcg_gen_exit_tb(0);
4069 gen_set_label(l1);
e0c8f9ce 4070 gen_update_nip(ctx, ctx->nip);
57fec1fe 4071 tcg_gen_exit_tb(0);
08e46e54 4072 }
a9e8f4e7 4073 if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
c80d1df5
AG
4074 tcg_temp_free(target);
4075 }
e98a6e40
FB
4076}
4077
99e300ef 4078static void gen_bc(DisasContext *ctx)
3b46e624 4079{
e98a6e40
FB
4080 gen_bcond(ctx, BCOND_IM);
4081}
4082
99e300ef 4083static void gen_bcctr(DisasContext *ctx)
3b46e624 4084{
e98a6e40
FB
4085 gen_bcond(ctx, BCOND_CTR);
4086}
4087
99e300ef 4088static void gen_bclr(DisasContext *ctx)
3b46e624 4089{
e98a6e40
FB
4090 gen_bcond(ctx, BCOND_LR);
4091}
79aceca5 4092
52a4984d
TM
4093static void gen_bctar(DisasContext *ctx)
4094{
4095 gen_bcond(ctx, BCOND_TAR);
4096}
4097
79aceca5 4098/*** Condition register logical ***/
e1571908 4099#define GEN_CRLOGIC(name, tcg_op, opc) \
99e300ef 4100static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 4101{ \
fc0d441e
JM
4102 uint8_t bitmask; \
4103 int sh; \
a7812ae4 4104 TCGv_i32 t0, t1; \
fc0d441e 4105 sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
a7812ae4 4106 t0 = tcg_temp_new_i32(); \
fc0d441e 4107 if (sh > 0) \
fea0c503 4108 tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \
fc0d441e 4109 else if (sh < 0) \
fea0c503 4110 tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \
e1571908 4111 else \
fea0c503 4112 tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \
a7812ae4 4113 t1 = tcg_temp_new_i32(); \
fc0d441e
JM
4114 sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
4115 if (sh > 0) \
fea0c503 4116 tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \
fc0d441e 4117 else if (sh < 0) \
fea0c503 4118 tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \
e1571908 4119 else \
fea0c503
AJ
4120 tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \
4121 tcg_op(t0, t0, t1); \
8f9fb7ac 4122 bitmask = 0x08 >> (crbD(ctx->opcode) & 0x03); \
fea0c503
AJ
4123 tcg_gen_andi_i32(t0, t0, bitmask); \
4124 tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
4125 tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \
a7812ae4
PB
4126 tcg_temp_free_i32(t0); \
4127 tcg_temp_free_i32(t1); \
79aceca5
FB
4128}
4129
4130/* crand */
e1571908 4131GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
79aceca5 4132/* crandc */
e1571908 4133GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
79aceca5 4134/* creqv */
e1571908 4135GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
79aceca5 4136/* crnand */
e1571908 4137GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
79aceca5 4138/* crnor */
e1571908 4139GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
79aceca5 4140/* cror */
e1571908 4141GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
79aceca5 4142/* crorc */
e1571908 4143GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
79aceca5 4144/* crxor */
e1571908 4145GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
99e300ef 4146
54623277 4147/* mcrf */
99e300ef 4148static void gen_mcrf(DisasContext *ctx)
79aceca5 4149{
47e4661c 4150 tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
79aceca5
FB
4151}
4152
4153/*** System linkage ***/
99e300ef 4154
c47493f2 4155/* rfi (supervisor only) */
99e300ef 4156static void gen_rfi(DisasContext *ctx)
79aceca5 4157{
9a64fbe4 4158#if defined(CONFIG_USER_ONLY)
9b2fadda 4159 GEN_PRIV;
9a64fbe4 4160#else
a2e71b28
BH
4161 /* FIXME: This instruction doesn't exist anymore on 64-bit server
4162 * processors compliant with arch 2.x, we should remove it there,
4163 * but we need to fix OpenBIOS not to use it on 970 first
4164 */
9a64fbe4 4165 /* Restore CPU state */
9b2fadda 4166 CHK_SV;
697ab892 4167 gen_update_cfar(ctx, ctx->nip);
e5f17ac6 4168 gen_helper_rfi(cpu_env);
e06fcd75 4169 gen_sync_exception(ctx);
9a64fbe4 4170#endif
79aceca5
FB
4171}
4172
426613db 4173#if defined(TARGET_PPC64)
99e300ef 4174static void gen_rfid(DisasContext *ctx)
426613db
JM
4175{
4176#if defined(CONFIG_USER_ONLY)
9b2fadda 4177 GEN_PRIV;
426613db
JM
4178#else
4179 /* Restore CPU state */
9b2fadda 4180 CHK_SV;
697ab892 4181 gen_update_cfar(ctx, ctx->nip);
e5f17ac6 4182 gen_helper_rfid(cpu_env);
e06fcd75 4183 gen_sync_exception(ctx);
426613db
JM
4184#endif
4185}
426613db 4186
99e300ef 4187static void gen_hrfid(DisasContext *ctx)
be147d08
JM
4188{
4189#if defined(CONFIG_USER_ONLY)
9b2fadda 4190 GEN_PRIV;
be147d08
JM
4191#else
4192 /* Restore CPU state */
9b2fadda 4193 CHK_HV;
e5f17ac6 4194 gen_helper_hrfid(cpu_env);
e06fcd75 4195 gen_sync_exception(ctx);
be147d08
JM
4196#endif
4197}
4198#endif
4199
79aceca5 4200/* sc */
417bf010
JM
4201#if defined(CONFIG_USER_ONLY)
4202#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
4203#else
4204#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
4205#endif
99e300ef 4206static void gen_sc(DisasContext *ctx)
79aceca5 4207{
e1833e1f
JM
4208 uint32_t lev;
4209
4210 lev = (ctx->opcode >> 5) & 0x7F;
e06fcd75 4211 gen_exception_err(ctx, POWERPC_SYSCALL, lev);
79aceca5
FB
4212}
4213
4214/*** Trap ***/
99e300ef 4215
54623277 4216/* tw */
99e300ef 4217static void gen_tw(DisasContext *ctx)
79aceca5 4218{
cab3bee2 4219 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
4220 /* Update the nip since this might generate a trap exception */
4221 gen_update_nip(ctx, ctx->nip);
e5f17ac6
BS
4222 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4223 t0);
cab3bee2 4224 tcg_temp_free_i32(t0);
79aceca5
FB
4225}
4226
4227/* twi */
99e300ef 4228static void gen_twi(DisasContext *ctx)
79aceca5 4229{
cab3bee2
AJ
4230 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
4231 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
4232 /* Update the nip since this might generate a trap exception */
4233 gen_update_nip(ctx, ctx->nip);
e5f17ac6 4234 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
cab3bee2
AJ
4235 tcg_temp_free(t0);
4236 tcg_temp_free_i32(t1);
79aceca5
FB
4237}
4238
d9bce9d9
JM
4239#if defined(TARGET_PPC64)
4240/* td */
99e300ef 4241static void gen_td(DisasContext *ctx)
d9bce9d9 4242{
cab3bee2 4243 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
4244 /* Update the nip since this might generate a trap exception */
4245 gen_update_nip(ctx, ctx->nip);
e5f17ac6
BS
4246 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4247 t0);
cab3bee2 4248 tcg_temp_free_i32(t0);
d9bce9d9
JM
4249}
4250
4251/* tdi */
99e300ef 4252static void gen_tdi(DisasContext *ctx)
d9bce9d9 4253{
cab3bee2
AJ
4254 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
4255 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
4256 /* Update the nip since this might generate a trap exception */
4257 gen_update_nip(ctx, ctx->nip);
e5f17ac6 4258 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
cab3bee2
AJ
4259 tcg_temp_free(t0);
4260 tcg_temp_free_i32(t1);
d9bce9d9
JM
4261}
4262#endif
4263
79aceca5 4264/*** Processor control ***/
99e300ef 4265
da91a00f
RH
4266static void gen_read_xer(TCGv dst)
4267{
4268 TCGv t0 = tcg_temp_new();
4269 TCGv t1 = tcg_temp_new();
4270 TCGv t2 = tcg_temp_new();
4271 tcg_gen_mov_tl(dst, cpu_xer);
4272 tcg_gen_shli_tl(t0, cpu_so, XER_SO);
4273 tcg_gen_shli_tl(t1, cpu_ov, XER_OV);
4274 tcg_gen_shli_tl(t2, cpu_ca, XER_CA);
4275 tcg_gen_or_tl(t0, t0, t1);
4276 tcg_gen_or_tl(dst, dst, t2);
4277 tcg_gen_or_tl(dst, dst, t0);
4278 tcg_temp_free(t0);
4279 tcg_temp_free(t1);
4280 tcg_temp_free(t2);
4281}
4282
4283static void gen_write_xer(TCGv src)
4284{
4285 tcg_gen_andi_tl(cpu_xer, src,
4286 ~((1u << XER_SO) | (1u << XER_OV) | (1u << XER_CA)));
4287 tcg_gen_shri_tl(cpu_so, src, XER_SO);
4288 tcg_gen_shri_tl(cpu_ov, src, XER_OV);
4289 tcg_gen_shri_tl(cpu_ca, src, XER_CA);
4290 tcg_gen_andi_tl(cpu_so, cpu_so, 1);
4291 tcg_gen_andi_tl(cpu_ov, cpu_ov, 1);
4292 tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
4293}
4294
54623277 4295/* mcrxr */
99e300ef 4296static void gen_mcrxr(DisasContext *ctx)
79aceca5 4297{
da91a00f
RH
4298 TCGv_i32 t0 = tcg_temp_new_i32();
4299 TCGv_i32 t1 = tcg_temp_new_i32();
4300 TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];
4301
4302 tcg_gen_trunc_tl_i32(t0, cpu_so);
4303 tcg_gen_trunc_tl_i32(t1, cpu_ov);
4304 tcg_gen_trunc_tl_i32(dst, cpu_ca);
294d1292
SB
4305 tcg_gen_shli_i32(t0, t0, 3);
4306 tcg_gen_shli_i32(t1, t1, 2);
4307 tcg_gen_shli_i32(dst, dst, 1);
da91a00f
RH
4308 tcg_gen_or_i32(dst, dst, t0);
4309 tcg_gen_or_i32(dst, dst, t1);
4310 tcg_temp_free_i32(t0);
4311 tcg_temp_free_i32(t1);
4312
4313 tcg_gen_movi_tl(cpu_so, 0);
4314 tcg_gen_movi_tl(cpu_ov, 0);
4315 tcg_gen_movi_tl(cpu_ca, 0);
79aceca5
FB
4316}
4317
0cfe11ea 4318/* mfcr mfocrf */
99e300ef 4319static void gen_mfcr(DisasContext *ctx)
79aceca5 4320{
76a66253 4321 uint32_t crm, crn;
3b46e624 4322
76a66253
JM
4323 if (likely(ctx->opcode & 0x00100000)) {
4324 crm = CRM(ctx->opcode);
8dd640e4 4325 if (likely(crm && ((crm & (crm - 1)) == 0))) {
0cfe11ea 4326 crn = ctz32 (crm);
e1571908 4327 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
0497d2f4
AJ
4328 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
4329 cpu_gpr[rD(ctx->opcode)], crn * 4);
76a66253 4330 }
d9bce9d9 4331 } else {
651721b2
AJ
4332 TCGv_i32 t0 = tcg_temp_new_i32();
4333 tcg_gen_mov_i32(t0, cpu_crf[0]);
4334 tcg_gen_shli_i32(t0, t0, 4);
4335 tcg_gen_or_i32(t0, t0, cpu_crf[1]);
4336 tcg_gen_shli_i32(t0, t0, 4);
4337 tcg_gen_or_i32(t0, t0, cpu_crf[2]);
4338 tcg_gen_shli_i32(t0, t0, 4);
4339 tcg_gen_or_i32(t0, t0, cpu_crf[3]);
4340 tcg_gen_shli_i32(t0, t0, 4);
4341 tcg_gen_or_i32(t0, t0, cpu_crf[4]);
4342 tcg_gen_shli_i32(t0, t0, 4);
4343 tcg_gen_or_i32(t0, t0, cpu_crf[5]);
4344 tcg_gen_shli_i32(t0, t0, 4);
4345 tcg_gen_or_i32(t0, t0, cpu_crf[6]);
4346 tcg_gen_shli_i32(t0, t0, 4);
4347 tcg_gen_or_i32(t0, t0, cpu_crf[7]);
4348 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
4349 tcg_temp_free_i32(t0);
d9bce9d9 4350 }
79aceca5
FB
4351}
4352
4353/* mfmsr */
99e300ef 4354static void gen_mfmsr(DisasContext *ctx)
79aceca5 4355{
9b2fadda 4356 CHK_SV;
6527f6ea 4357 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
79aceca5
FB
4358}
4359
69b058c8 4360static void spr_noaccess(DisasContext *ctx, int gprn, int sprn)
3fc6c082 4361{
7b13448f 4362#if 0
3fc6c082
FB
4363 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
4364 printf("ERROR: try to access SPR %d !\n", sprn);
7b13448f 4365#endif
3fc6c082
FB
4366}
4367#define SPR_NOACCESS (&spr_noaccess)
3fc6c082 4368
79aceca5 4369/* mfspr */
636aa200 4370static inline void gen_op_mfspr(DisasContext *ctx)
79aceca5 4371{
69b058c8 4372 void (*read_cb)(DisasContext *ctx, int gprn, int sprn);
79aceca5
FB
4373 uint32_t sprn = SPR(ctx->opcode);
4374
eb94268e
BH
4375#if defined(CONFIG_USER_ONLY)
4376 read_cb = ctx->spr_cb[sprn].uea_read;
4377#else
4378 if (ctx->pr) {
4379 read_cb = ctx->spr_cb[sprn].uea_read;
4380 } else if (ctx->hv) {
be147d08 4381 read_cb = ctx->spr_cb[sprn].hea_read;
eb94268e 4382 } else {
3fc6c082 4383 read_cb = ctx->spr_cb[sprn].oea_read;
eb94268e 4384 }
9a64fbe4 4385#endif
76a66253
JM
4386 if (likely(read_cb != NULL)) {
4387 if (likely(read_cb != SPR_NOACCESS)) {
45d827d2 4388 (*read_cb)(ctx, rD(ctx->opcode), sprn);
3fc6c082
FB
4389 } else {
4390 /* Privilege exception */
9fceefa7
JM
4391 /* This is a hack to avoid warnings when running Linux:
4392 * this OS breaks the PowerPC virtualisation model,
4393 * allowing userland application to read the PVR
4394 */
4395 if (sprn != SPR_PVR) {
013a2942
PB
4396 fprintf(stderr, "Trying to read privileged spr %d (0x%03x) at "
4397 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4398 if (qemu_log_separate()) {
4399 qemu_log("Trying to read privileged spr %d (0x%03x) at "
4400 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4401 }
f24e5695 4402 }
9b2fadda 4403 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
79aceca5 4404 }
3fc6c082 4405 } else {
9b2fadda
BH
4406 /* ISA 2.07 defines these as no-ops */
4407 if ((ctx->insns_flags2 & PPC2_ISA207S) &&
4408 (sprn >= 808 && sprn <= 811)) {
4409 /* This is a nop */
4410 return;
4411 }
3fc6c082 4412 /* Not defined */
013a2942
PB
4413 fprintf(stderr, "Trying to read invalid spr %d (0x%03x) at "
4414 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4415 if (qemu_log_separate()) {
4416 qemu_log("Trying to read invalid spr %d (0x%03x) at "
4417 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4418 }
9b2fadda
BH
4419
4420 /* The behaviour depends on MSR:PR and SPR# bit 0x10,
4421 * it can generate a priv, a hv emu or a no-op
4422 */
4423 if (sprn & 0x10) {
4424 if (ctx->pr) {
4425 gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4426 }
4427 } else {
4428 if (ctx->pr || sprn == 0 || sprn == 4 || sprn == 5 || sprn == 6) {
4429 gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4430 }
4d6a0680 4431 }
79aceca5 4432 }
79aceca5
FB
4433}
4434
99e300ef 4435static void gen_mfspr(DisasContext *ctx)
79aceca5 4436{
3fc6c082 4437 gen_op_mfspr(ctx);
76a66253 4438}
3fc6c082
FB
4439
4440/* mftb */
99e300ef 4441static void gen_mftb(DisasContext *ctx)
3fc6c082
FB
4442{
4443 gen_op_mfspr(ctx);
79aceca5
FB
4444}
4445
0cfe11ea 4446/* mtcrf mtocrf*/
99e300ef 4447static void gen_mtcrf(DisasContext *ctx)
79aceca5 4448{
76a66253 4449 uint32_t crm, crn;
3b46e624 4450
76a66253 4451 crm = CRM(ctx->opcode);
8dd640e4 4452 if (likely((ctx->opcode & 0x00100000))) {
4453 if (crm && ((crm & (crm - 1)) == 0)) {
4454 TCGv_i32 temp = tcg_temp_new_i32();
0cfe11ea 4455 crn = ctz32 (crm);
8dd640e4 4456 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
0cfe11ea
AJ
4457 tcg_gen_shri_i32(temp, temp, crn * 4);
4458 tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
8dd640e4 4459 tcg_temp_free_i32(temp);
4460 }
76a66253 4461 } else {
651721b2
AJ
4462 TCGv_i32 temp = tcg_temp_new_i32();
4463 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
4464 for (crn = 0 ; crn < 8 ; crn++) {
4465 if (crm & (1 << crn)) {
4466 tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
4467 tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
4468 }
4469 }
a7812ae4 4470 tcg_temp_free_i32(temp);
76a66253 4471 }
79aceca5
FB
4472}
4473
4474/* mtmsr */
426613db 4475#if defined(TARGET_PPC64)
99e300ef 4476static void gen_mtmsrd(DisasContext *ctx)
426613db 4477{
9b2fadda
BH
4478 CHK_SV;
4479
4480#if !defined(CONFIG_USER_ONLY)
be147d08
JM
4481 if (ctx->opcode & 0x00010000) {
4482 /* Special form that does not need any synchronisation */
6527f6ea
AJ
4483 TCGv t0 = tcg_temp_new();
4484 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
c409bc5d 4485 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
6527f6ea
AJ
4486 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
4487 tcg_temp_free(t0);
be147d08 4488 } else {
056b05f8
JM
4489 /* XXX: we need to update nip before the store
4490 * if we enter power saving mode, we will exit the loop
4491 * directly from ppc_store_msr
4492 */
be147d08 4493 gen_update_nip(ctx, ctx->nip);
e5f17ac6 4494 gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
be147d08
JM
4495 /* Must stop the translation as machine state (may have) changed */
4496 /* Note that mtmsr is not always defined as context-synchronizing */
e06fcd75 4497 gen_stop_exception(ctx);
be147d08 4498 }
9b2fadda 4499#endif /* !defined(CONFIG_USER_ONLY) */
426613db 4500}
9b2fadda 4501#endif /* defined(TARGET_PPC64) */
426613db 4502
99e300ef 4503static void gen_mtmsr(DisasContext *ctx)
79aceca5 4504{
9b2fadda
BH
4505 CHK_SV;
4506
4507#if !defined(CONFIG_USER_ONLY)
4508 if (ctx->opcode & 0x00010000) {
be147d08 4509 /* Special form that does not need any synchronisation */
6527f6ea
AJ
4510 TCGv t0 = tcg_temp_new();
4511 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
c409bc5d 4512 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
6527f6ea
AJ
4513 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
4514 tcg_temp_free(t0);
be147d08 4515 } else {
8018dc63
AG
4516 TCGv msr = tcg_temp_new();
4517
056b05f8
JM
4518 /* XXX: we need to update nip before the store
4519 * if we enter power saving mode, we will exit the loop
4520 * directly from ppc_store_msr
4521 */
be147d08 4522 gen_update_nip(ctx, ctx->nip);
d9bce9d9 4523#if defined(TARGET_PPC64)
8018dc63
AG
4524 tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
4525#else
4526 tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
d9bce9d9 4527#endif
e5f17ac6 4528 gen_helper_store_msr(cpu_env, msr);
c80d1df5 4529 tcg_temp_free(msr);
be147d08 4530 /* Must stop the translation as machine state (may have) changed */
6527f6ea 4531 /* Note that mtmsr is not always defined as context-synchronizing */
e06fcd75 4532 gen_stop_exception(ctx);
be147d08 4533 }
9a64fbe4 4534#endif
79aceca5
FB
4535}
4536
4537/* mtspr */
99e300ef 4538static void gen_mtspr(DisasContext *ctx)
79aceca5 4539{
69b058c8 4540 void (*write_cb)(DisasContext *ctx, int sprn, int gprn);
79aceca5
FB
4541 uint32_t sprn = SPR(ctx->opcode);
4542
eb94268e
BH
4543#if defined(CONFIG_USER_ONLY)
4544 write_cb = ctx->spr_cb[sprn].uea_write;
4545#else
4546 if (ctx->pr) {
4547 write_cb = ctx->spr_cb[sprn].uea_write;
4548 } else if (ctx->hv) {
be147d08 4549 write_cb = ctx->spr_cb[sprn].hea_write;
eb94268e 4550 } else {
3fc6c082 4551 write_cb = ctx->spr_cb[sprn].oea_write;
eb94268e 4552 }
9a64fbe4 4553#endif
76a66253
JM
4554 if (likely(write_cb != NULL)) {
4555 if (likely(write_cb != SPR_NOACCESS)) {
45d827d2 4556 (*write_cb)(ctx, sprn, rS(ctx->opcode));
3fc6c082
FB
4557 } else {
4558 /* Privilege exception */
013a2942
PB
4559 fprintf(stderr, "Trying to write privileged spr %d (0x%03x) at "
4560 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4561 if (qemu_log_separate()) {
4562 qemu_log("Trying to write privileged spr %d (0x%03x) at "
4563 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4564 }
9b2fadda 4565 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253 4566 }
3fc6c082 4567 } else {
9b2fadda
BH
4568 /* ISA 2.07 defines these as no-ops */
4569 if ((ctx->insns_flags2 & PPC2_ISA207S) &&
4570 (sprn >= 808 && sprn <= 811)) {
4571 /* This is a nop */
4572 return;
4573 }
4574
3fc6c082 4575 /* Not defined */
013a2942
PB
4576 if (qemu_log_separate()) {
4577 qemu_log("Trying to write invalid spr %d (0x%03x) at "
4578 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4579 }
4580 fprintf(stderr, "Trying to write invalid spr %d (0x%03x) at "
4581 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4d6a0680 4582
9b2fadda
BH
4583
4584 /* The behaviour depends on MSR:PR and SPR# bit 0x10,
4585 * it can generate a priv, a hv emu or a no-op
4586 */
4587 if (sprn & 0x10) {
4588 if (ctx->pr) {
4589 gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4590 }
4591 } else {
4592 if (ctx->pr || sprn == 0) {
4593 gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
4594 }
4d6a0680 4595 }
79aceca5 4596 }
79aceca5
FB
4597}
4598
4599/*** Cache management ***/
99e300ef 4600
54623277 4601/* dcbf */
99e300ef 4602static void gen_dcbf(DisasContext *ctx)
79aceca5 4603{
dac454af 4604 /* XXX: specification says this is treated as a load by the MMU */
76db3ba4
AJ
4605 TCGv t0;
4606 gen_set_access_type(ctx, ACCESS_CACHE);
4607 t0 = tcg_temp_new();
4608 gen_addr_reg_index(ctx, t0);
4609 gen_qemu_ld8u(ctx, t0, t0);
fea0c503 4610 tcg_temp_free(t0);
79aceca5
FB
4611}
4612
4613/* dcbi (Supervisor only) */
99e300ef 4614static void gen_dcbi(DisasContext *ctx)
79aceca5 4615{
a541f297 4616#if defined(CONFIG_USER_ONLY)
9b2fadda 4617 GEN_PRIV;
a541f297 4618#else
b61f2753 4619 TCGv EA, val;
9b2fadda
BH
4620
4621 CHK_SV;
a7812ae4 4622 EA = tcg_temp_new();
76db3ba4
AJ
4623 gen_set_access_type(ctx, ACCESS_CACHE);
4624 gen_addr_reg_index(ctx, EA);
a7812ae4 4625 val = tcg_temp_new();
76a66253 4626 /* XXX: specification says this should be treated as a store by the MMU */
76db3ba4
AJ
4627 gen_qemu_ld8u(ctx, val, EA);
4628 gen_qemu_st8(ctx, val, EA);
b61f2753
AJ
4629 tcg_temp_free(val);
4630 tcg_temp_free(EA);
9b2fadda 4631#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
4632}
4633
4634/* dcdst */
99e300ef 4635static void gen_dcbst(DisasContext *ctx)
79aceca5 4636{
76a66253 4637 /* XXX: specification say this is treated as a load by the MMU */
76db3ba4
AJ
4638 TCGv t0;
4639 gen_set_access_type(ctx, ACCESS_CACHE);
4640 t0 = tcg_temp_new();
4641 gen_addr_reg_index(ctx, t0);
4642 gen_qemu_ld8u(ctx, t0, t0);
fea0c503 4643 tcg_temp_free(t0);
79aceca5
FB
4644}
4645
4646/* dcbt */
99e300ef 4647static void gen_dcbt(DisasContext *ctx)
79aceca5 4648{
0db1b20e 4649 /* interpreted as no-op */
76a66253
JM
4650 /* XXX: specification say this is treated as a load by the MMU
4651 * but does not generate any exception
4652 */
79aceca5
FB
4653}
4654
4655/* dcbtst */
99e300ef 4656static void gen_dcbtst(DisasContext *ctx)
79aceca5 4657{
0db1b20e 4658 /* interpreted as no-op */
76a66253
JM
4659 /* XXX: specification say this is treated as a load by the MMU
4660 * but does not generate any exception
4661 */
79aceca5
FB
4662}
4663
4d09d529
AG
4664/* dcbtls */
4665static void gen_dcbtls(DisasContext *ctx)
4666{
4667 /* Always fails locking the cache */
4668 TCGv t0 = tcg_temp_new();
4669 gen_load_spr(t0, SPR_Exxx_L1CSR0);
4670 tcg_gen_ori_tl(t0, t0, L1CSR0_CUL);
4671 gen_store_spr(SPR_Exxx_L1CSR0, t0);
4672 tcg_temp_free(t0);
4673}
4674
79aceca5 4675/* dcbz */
99e300ef 4676static void gen_dcbz(DisasContext *ctx)
79aceca5 4677{
8e33944f
AG
4678 TCGv tcgv_addr;
4679 TCGv_i32 tcgv_is_dcbzl;
4680 int is_dcbzl = ctx->opcode & 0x00200000 ? 1 : 0;
d63001d1 4681
76db3ba4 4682 gen_set_access_type(ctx, ACCESS_CACHE);
799a8c8d
AJ
4683 /* NIP cannot be restored if the memory exception comes from an helper */
4684 gen_update_nip(ctx, ctx->nip - 4);
8e33944f
AG
4685 tcgv_addr = tcg_temp_new();
4686 tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);
4687
4688 gen_addr_reg_index(ctx, tcgv_addr);
4689 gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_is_dcbzl);
4690
4691 tcg_temp_free(tcgv_addr);
4692 tcg_temp_free_i32(tcgv_is_dcbzl);
79aceca5
FB
4693}
4694
ae1c1a3d 4695/* dst / dstt */
99e300ef 4696static void gen_dst(DisasContext *ctx)
ae1c1a3d
AJ
4697{
4698 if (rA(ctx->opcode) == 0) {
4699 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4700 } else {
4701 /* interpreted as no-op */
4702 }
4703}
4704
4705/* dstst /dststt */
99e300ef 4706static void gen_dstst(DisasContext *ctx)
ae1c1a3d
AJ
4707{
4708 if (rA(ctx->opcode) == 0) {
4709 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4710 } else {
4711 /* interpreted as no-op */
4712 }
4713
4714}
4715
4716/* dss / dssall */
99e300ef 4717static void gen_dss(DisasContext *ctx)
ae1c1a3d
AJ
4718{
4719 /* interpreted as no-op */
4720}
4721
79aceca5 4722/* icbi */
99e300ef 4723static void gen_icbi(DisasContext *ctx)
79aceca5 4724{
76db3ba4
AJ
4725 TCGv t0;
4726 gen_set_access_type(ctx, ACCESS_CACHE);
30032c94
JM
4727 /* NIP cannot be restored if the memory exception comes from an helper */
4728 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
4729 t0 = tcg_temp_new();
4730 gen_addr_reg_index(ctx, t0);
2f5a189c 4731 gen_helper_icbi(cpu_env, t0);
37d269df 4732 tcg_temp_free(t0);
79aceca5
FB
4733}
4734
4735/* Optional: */
4736/* dcba */
99e300ef 4737static void gen_dcba(DisasContext *ctx)
79aceca5 4738{
0db1b20e
JM
4739 /* interpreted as no-op */
4740 /* XXX: specification say this is treated as a store by the MMU
4741 * but does not generate any exception
4742 */
79aceca5
FB
4743}
4744
4745/*** Segment register manipulation ***/
4746/* Supervisor only: */
99e300ef 4747
54623277 4748/* mfsr */
99e300ef 4749static void gen_mfsr(DisasContext *ctx)
79aceca5 4750{
9a64fbe4 4751#if defined(CONFIG_USER_ONLY)
9b2fadda 4752 GEN_PRIV;
9a64fbe4 4753#else
74d37793 4754 TCGv t0;
9b2fadda
BH
4755
4756 CHK_SV;
74d37793 4757 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 4758 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 4759 tcg_temp_free(t0);
9b2fadda 4760#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
4761}
4762
4763/* mfsrin */
99e300ef 4764static void gen_mfsrin(DisasContext *ctx)
79aceca5 4765{
9a64fbe4 4766#if defined(CONFIG_USER_ONLY)
9b2fadda 4767 GEN_PRIV;
9a64fbe4 4768#else
74d37793 4769 TCGv t0;
9b2fadda
BH
4770
4771 CHK_SV;
74d37793
AJ
4772 t0 = tcg_temp_new();
4773 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4774 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 4775 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 4776 tcg_temp_free(t0);
9b2fadda 4777#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
4778}
4779
4780/* mtsr */
99e300ef 4781static void gen_mtsr(DisasContext *ctx)
79aceca5 4782{
9a64fbe4 4783#if defined(CONFIG_USER_ONLY)
9b2fadda 4784 GEN_PRIV;
9a64fbe4 4785#else
74d37793 4786 TCGv t0;
9b2fadda
BH
4787
4788 CHK_SV;
74d37793 4789 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 4790 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 4791 tcg_temp_free(t0);
9b2fadda 4792#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
4793}
4794
4795/* mtsrin */
99e300ef 4796static void gen_mtsrin(DisasContext *ctx)
79aceca5 4797{
9a64fbe4 4798#if defined(CONFIG_USER_ONLY)
9b2fadda 4799 GEN_PRIV;
9a64fbe4 4800#else
74d37793 4801 TCGv t0;
9b2fadda
BH
4802 CHK_SV;
4803
74d37793
AJ
4804 t0 = tcg_temp_new();
4805 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4806 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 4807 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
74d37793 4808 tcg_temp_free(t0);
9b2fadda 4809#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
4810}
4811
12de9a39
JM
4812#if defined(TARGET_PPC64)
4813/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
e8eaa2c0 4814
54623277 4815/* mfsr */
e8eaa2c0 4816static void gen_mfsr_64b(DisasContext *ctx)
12de9a39
JM
4817{
4818#if defined(CONFIG_USER_ONLY)
9b2fadda 4819 GEN_PRIV;
12de9a39 4820#else
74d37793 4821 TCGv t0;
9b2fadda
BH
4822
4823 CHK_SV;
74d37793 4824 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 4825 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 4826 tcg_temp_free(t0);
9b2fadda 4827#endif /* defined(CONFIG_USER_ONLY) */
12de9a39
JM
4828}
4829
4830/* mfsrin */
e8eaa2c0 4831static void gen_mfsrin_64b(DisasContext *ctx)
12de9a39
JM
4832{
4833#if defined(CONFIG_USER_ONLY)
9b2fadda 4834 GEN_PRIV;
12de9a39 4835#else
74d37793 4836 TCGv t0;
9b2fadda
BH
4837
4838 CHK_SV;
74d37793
AJ
4839 t0 = tcg_temp_new();
4840 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4841 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 4842 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 4843 tcg_temp_free(t0);
9b2fadda 4844#endif /* defined(CONFIG_USER_ONLY) */
12de9a39
JM
4845}
4846
4847/* mtsr */
e8eaa2c0 4848static void gen_mtsr_64b(DisasContext *ctx)
12de9a39
JM
4849{
4850#if defined(CONFIG_USER_ONLY)
9b2fadda 4851 GEN_PRIV;
12de9a39 4852#else
74d37793 4853 TCGv t0;
9b2fadda
BH
4854
4855 CHK_SV;
74d37793 4856 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 4857 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 4858 tcg_temp_free(t0);
9b2fadda 4859#endif /* defined(CONFIG_USER_ONLY) */
12de9a39
JM
4860}
4861
4862/* mtsrin */
e8eaa2c0 4863static void gen_mtsrin_64b(DisasContext *ctx)
12de9a39
JM
4864{
4865#if defined(CONFIG_USER_ONLY)
9b2fadda 4866 GEN_PRIV;
12de9a39 4867#else
74d37793 4868 TCGv t0;
9b2fadda
BH
4869
4870 CHK_SV;
74d37793
AJ
4871 t0 = tcg_temp_new();
4872 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4873 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 4874 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 4875 tcg_temp_free(t0);
9b2fadda 4876#endif /* defined(CONFIG_USER_ONLY) */
12de9a39 4877}
f6b868fc
BS
4878
4879/* slbmte */
e8eaa2c0 4880static void gen_slbmte(DisasContext *ctx)
f6b868fc
BS
4881{
4882#if defined(CONFIG_USER_ONLY)
9b2fadda 4883 GEN_PRIV;
f6b868fc 4884#else
9b2fadda
BH
4885 CHK_SV;
4886
c6c7cf05
BS
4887 gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
4888 cpu_gpr[rS(ctx->opcode)]);
9b2fadda 4889#endif /* defined(CONFIG_USER_ONLY) */
f6b868fc
BS
4890}
4891
efdef95f
DG
4892static void gen_slbmfee(DisasContext *ctx)
4893{
4894#if defined(CONFIG_USER_ONLY)
9b2fadda 4895 GEN_PRIV;
efdef95f 4896#else
9b2fadda
BH
4897 CHK_SV;
4898
c6c7cf05 4899 gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
efdef95f 4900 cpu_gpr[rB(ctx->opcode)]);
9b2fadda 4901#endif /* defined(CONFIG_USER_ONLY) */
efdef95f
DG
4902}
4903
4904static void gen_slbmfev(DisasContext *ctx)
4905{
4906#if defined(CONFIG_USER_ONLY)
9b2fadda 4907 GEN_PRIV;
efdef95f 4908#else
9b2fadda
BH
4909 CHK_SV;
4910
c6c7cf05 4911 gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
efdef95f 4912 cpu_gpr[rB(ctx->opcode)]);
9b2fadda 4913#endif /* defined(CONFIG_USER_ONLY) */
efdef95f 4914}
c76c22d5
BH
4915
4916static void gen_slbfee_(DisasContext *ctx)
4917{
4918#if defined(CONFIG_USER_ONLY)
4919 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4920#else
4921 TCGLabel *l1, *l2;
4922
4923 if (unlikely(ctx->pr)) {
4924 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4925 return;
4926 }
4927 gen_helper_find_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
4928 cpu_gpr[rB(ctx->opcode)]);
4929 l1 = gen_new_label();
4930 l2 = gen_new_label();
4931 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
4932 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rS(ctx->opcode)], -1, l1);
4933 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
4934 tcg_gen_br(l2);
4935 gen_set_label(l1);
4936 tcg_gen_movi_tl(cpu_gpr[rS(ctx->opcode)], 0);
4937 gen_set_label(l2);
4938#endif
4939}
12de9a39
JM
4940#endif /* defined(TARGET_PPC64) */
4941
79aceca5 4942/*** Lookaside buffer management ***/
c47493f2 4943/* Optional & supervisor only: */
99e300ef 4944
54623277 4945/* tlbia */
99e300ef 4946static void gen_tlbia(DisasContext *ctx)
79aceca5 4947{
9a64fbe4 4948#if defined(CONFIG_USER_ONLY)
9b2fadda 4949 GEN_PRIV;
9a64fbe4 4950#else
9b2fadda
BH
4951 CHK_HV;
4952
c6c7cf05 4953 gen_helper_tlbia(cpu_env);
9b2fadda 4954#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
4955}
4956
bf14b1ce 4957/* tlbiel */
99e300ef 4958static void gen_tlbiel(DisasContext *ctx)
bf14b1ce
BS
4959{
4960#if defined(CONFIG_USER_ONLY)
9b2fadda 4961 GEN_PRIV;
bf14b1ce 4962#else
9b2fadda
BH
4963 CHK_SV;
4964
c6c7cf05 4965 gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9b2fadda 4966#endif /* defined(CONFIG_USER_ONLY) */
bf14b1ce
BS
4967}
4968
79aceca5 4969/* tlbie */
99e300ef 4970static void gen_tlbie(DisasContext *ctx)
79aceca5 4971{
9a64fbe4 4972#if defined(CONFIG_USER_ONLY)
9b2fadda 4973 GEN_PRIV;
9a64fbe4 4974#else
9b2fadda
BH
4975 CHK_HV;
4976
9ca3f7f3 4977 if (NARROW_MODE(ctx)) {
74d37793
AJ
4978 TCGv t0 = tcg_temp_new();
4979 tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
c6c7cf05 4980 gen_helper_tlbie(cpu_env, t0);
74d37793 4981 tcg_temp_free(t0);
9ca3f7f3 4982 } else {
c6c7cf05 4983 gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9ca3f7f3 4984 }
9b2fadda 4985#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
4986}
4987
4988/* tlbsync */
99e300ef 4989static void gen_tlbsync(DisasContext *ctx)
79aceca5 4990{
9a64fbe4 4991#if defined(CONFIG_USER_ONLY)
9b2fadda 4992 GEN_PRIV;
9a64fbe4 4993#else
9b2fadda
BH
4994 CHK_HV;
4995
cd0c6f47
BH
4996 /* tlbsync is a nop for server, ptesync handles delayed tlb flush,
4997 * embedded however needs to deal with tlbsync. We don't try to be
4998 * fancy and swallow the overhead of checking for both.
9a64fbe4 4999 */
cd0c6f47 5000 gen_check_tlb_flush(ctx);
9b2fadda 5001#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
5002}
5003
426613db
JM
5004#if defined(TARGET_PPC64)
5005/* slbia */
99e300ef 5006static void gen_slbia(DisasContext *ctx)
426613db
JM
5007{
5008#if defined(CONFIG_USER_ONLY)
9b2fadda 5009 GEN_PRIV;
426613db 5010#else
9b2fadda
BH
5011 CHK_SV;
5012
c6c7cf05 5013 gen_helper_slbia(cpu_env);
9b2fadda 5014#endif /* defined(CONFIG_USER_ONLY) */
426613db
JM
5015}
5016
5017/* slbie */
99e300ef 5018static void gen_slbie(DisasContext *ctx)
426613db
JM
5019{
5020#if defined(CONFIG_USER_ONLY)
9b2fadda 5021 GEN_PRIV;
426613db 5022#else
9b2fadda
BH
5023 CHK_SV;
5024
c6c7cf05 5025 gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9b2fadda 5026#endif /* defined(CONFIG_USER_ONLY) */
426613db 5027}
9b2fadda 5028#endif /* defined(TARGET_PPC64) */
426613db 5029
79aceca5
FB
5030/*** External control ***/
5031/* Optional: */
99e300ef 5032
54623277 5033/* eciwx */
99e300ef 5034static void gen_eciwx(DisasContext *ctx)
79aceca5 5035{
76db3ba4 5036 TCGv t0;
fa407c03 5037 /* Should check EAR[E] ! */
76db3ba4
AJ
5038 gen_set_access_type(ctx, ACCESS_EXT);
5039 t0 = tcg_temp_new();
5040 gen_addr_reg_index(ctx, t0);
fa407c03 5041 gen_check_align(ctx, t0, 0x03);
76db3ba4 5042 gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
fa407c03 5043 tcg_temp_free(t0);
76a66253
JM
5044}
5045
5046/* ecowx */
99e300ef 5047static void gen_ecowx(DisasContext *ctx)
76a66253 5048{
76db3ba4 5049 TCGv t0;
fa407c03 5050 /* Should check EAR[E] ! */
76db3ba4
AJ
5051 gen_set_access_type(ctx, ACCESS_EXT);
5052 t0 = tcg_temp_new();
5053 gen_addr_reg_index(ctx, t0);
fa407c03 5054 gen_check_align(ctx, t0, 0x03);
76db3ba4 5055 gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
fa407c03 5056 tcg_temp_free(t0);
76a66253
JM
5057}
5058
5059/* PowerPC 601 specific instructions */
99e300ef 5060
54623277 5061/* abs - abs. */
99e300ef 5062static void gen_abs(DisasContext *ctx)
76a66253 5063{
42a268c2
RH
5064 TCGLabel *l1 = gen_new_label();
5065 TCGLabel *l2 = gen_new_label();
22e0e173
AJ
5066 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
5067 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5068 tcg_gen_br(l2);
5069 gen_set_label(l1);
5070 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5071 gen_set_label(l2);
76a66253 5072 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5073 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5074}
5075
5076/* abso - abso. */
99e300ef 5077static void gen_abso(DisasContext *ctx)
76a66253 5078{
42a268c2
RH
5079 TCGLabel *l1 = gen_new_label();
5080 TCGLabel *l2 = gen_new_label();
5081 TCGLabel *l3 = gen_new_label();
22e0e173 5082 /* Start with XER OV disabled, the most likely case */
da91a00f 5083 tcg_gen_movi_tl(cpu_ov, 0);
22e0e173
AJ
5084 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
5085 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
da91a00f
RH
5086 tcg_gen_movi_tl(cpu_ov, 1);
5087 tcg_gen_movi_tl(cpu_so, 1);
22e0e173
AJ
5088 tcg_gen_br(l2);
5089 gen_set_label(l1);
5090 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5091 tcg_gen_br(l3);
5092 gen_set_label(l2);
5093 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5094 gen_set_label(l3);
76a66253 5095 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5096 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5097}
5098
5099/* clcs */
99e300ef 5100static void gen_clcs(DisasContext *ctx)
76a66253 5101{
22e0e173 5102 TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
d523dd00 5103 gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
22e0e173 5104 tcg_temp_free_i32(t0);
c7697e1f 5105 /* Rc=1 sets CR0 to an undefined state */
76a66253
JM
5106}
5107
5108/* div - div. */
99e300ef 5109static void gen_div(DisasContext *ctx)
76a66253 5110{
d15f74fb
BS
5111 gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
5112 cpu_gpr[rB(ctx->opcode)]);
76a66253 5113 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5114 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5115}
5116
5117/* divo - divo. */
99e300ef 5118static void gen_divo(DisasContext *ctx)
76a66253 5119{
d15f74fb
BS
5120 gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
5121 cpu_gpr[rB(ctx->opcode)]);
76a66253 5122 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5123 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5124}
5125
5126/* divs - divs. */
99e300ef 5127static void gen_divs(DisasContext *ctx)
76a66253 5128{
d15f74fb
BS
5129 gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
5130 cpu_gpr[rB(ctx->opcode)]);
76a66253 5131 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5132 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5133}
5134
5135/* divso - divso. */
99e300ef 5136static void gen_divso(DisasContext *ctx)
76a66253 5137{
d15f74fb
BS
5138 gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
5139 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 5140 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5141 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5142}
5143
5144/* doz - doz. */
99e300ef 5145static void gen_doz(DisasContext *ctx)
76a66253 5146{
42a268c2
RH
5147 TCGLabel *l1 = gen_new_label();
5148 TCGLabel *l2 = gen_new_label();
22e0e173
AJ
5149 tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
5150 tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5151 tcg_gen_br(l2);
5152 gen_set_label(l1);
5153 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
5154 gen_set_label(l2);
76a66253 5155 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5156 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5157}
5158
5159/* dozo - dozo. */
99e300ef 5160static void gen_dozo(DisasContext *ctx)
76a66253 5161{
42a268c2
RH
5162 TCGLabel *l1 = gen_new_label();
5163 TCGLabel *l2 = gen_new_label();
22e0e173
AJ
5164 TCGv t0 = tcg_temp_new();
5165 TCGv t1 = tcg_temp_new();
5166 TCGv t2 = tcg_temp_new();
5167 /* Start with XER OV disabled, the most likely case */
da91a00f 5168 tcg_gen_movi_tl(cpu_ov, 0);
22e0e173
AJ
5169 tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
5170 tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5171 tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5172 tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
5173 tcg_gen_andc_tl(t1, t1, t2);
5174 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
5175 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
da91a00f
RH
5176 tcg_gen_movi_tl(cpu_ov, 1);
5177 tcg_gen_movi_tl(cpu_so, 1);
22e0e173
AJ
5178 tcg_gen_br(l2);
5179 gen_set_label(l1);
5180 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
5181 gen_set_label(l2);
5182 tcg_temp_free(t0);
5183 tcg_temp_free(t1);
5184 tcg_temp_free(t2);
76a66253 5185 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5186 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5187}
5188
5189/* dozi */
99e300ef 5190static void gen_dozi(DisasContext *ctx)
76a66253 5191{
22e0e173 5192 target_long simm = SIMM(ctx->opcode);
42a268c2
RH
5193 TCGLabel *l1 = gen_new_label();
5194 TCGLabel *l2 = gen_new_label();
22e0e173
AJ
5195 tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
5196 tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
5197 tcg_gen_br(l2);
5198 gen_set_label(l1);
5199 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
5200 gen_set_label(l2);
5201 if (unlikely(Rc(ctx->opcode) != 0))
5202 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5203}
5204
76a66253 5205/* lscbx - lscbx. */
99e300ef 5206static void gen_lscbx(DisasContext *ctx)
76a66253 5207{
bdb4b689
AJ
5208 TCGv t0 = tcg_temp_new();
5209 TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
5210 TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
5211 TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
76a66253 5212
76db3ba4 5213 gen_addr_reg_index(ctx, t0);
76a66253 5214 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 5215 gen_update_nip(ctx, ctx->nip - 4);
2f5a189c 5216 gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
bdb4b689
AJ
5217 tcg_temp_free_i32(t1);
5218 tcg_temp_free_i32(t2);
5219 tcg_temp_free_i32(t3);
3d7b417e 5220 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
bdb4b689 5221 tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
76a66253 5222 if (unlikely(Rc(ctx->opcode) != 0))
bdb4b689
AJ
5223 gen_set_Rc0(ctx, t0);
5224 tcg_temp_free(t0);
76a66253
JM
5225}
5226
5227/* maskg - maskg. */
99e300ef 5228static void gen_maskg(DisasContext *ctx)
76a66253 5229{
42a268c2 5230 TCGLabel *l1 = gen_new_label();
22e0e173
AJ
5231 TCGv t0 = tcg_temp_new();
5232 TCGv t1 = tcg_temp_new();
5233 TCGv t2 = tcg_temp_new();
5234 TCGv t3 = tcg_temp_new();
5235 tcg_gen_movi_tl(t3, 0xFFFFFFFF);
5236 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5237 tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
5238 tcg_gen_addi_tl(t2, t0, 1);
5239 tcg_gen_shr_tl(t2, t3, t2);
5240 tcg_gen_shr_tl(t3, t3, t1);
5241 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
5242 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5243 tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5244 gen_set_label(l1);
5245 tcg_temp_free(t0);
5246 tcg_temp_free(t1);
5247 tcg_temp_free(t2);
5248 tcg_temp_free(t3);
76a66253 5249 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5250 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5251}
5252
5253/* maskir - maskir. */
99e300ef 5254static void gen_maskir(DisasContext *ctx)
76a66253 5255{
22e0e173
AJ
5256 TCGv t0 = tcg_temp_new();
5257 TCGv t1 = tcg_temp_new();
5258 tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
5259 tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
5260 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5261 tcg_temp_free(t0);
5262 tcg_temp_free(t1);
76a66253 5263 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5264 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5265}
5266
5267/* mul - mul. */
99e300ef 5268static void gen_mul(DisasContext *ctx)
76a66253 5269{
22e0e173
AJ
5270 TCGv_i64 t0 = tcg_temp_new_i64();
5271 TCGv_i64 t1 = tcg_temp_new_i64();
5272 TCGv t2 = tcg_temp_new();
5273 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
5274 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
5275 tcg_gen_mul_i64(t0, t0, t1);
5276 tcg_gen_trunc_i64_tl(t2, t0);
5277 gen_store_spr(SPR_MQ, t2);
5278 tcg_gen_shri_i64(t1, t0, 32);
5279 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
5280 tcg_temp_free_i64(t0);
5281 tcg_temp_free_i64(t1);
5282 tcg_temp_free(t2);
76a66253 5283 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5284 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5285}
5286
5287/* mulo - mulo. */
99e300ef 5288static void gen_mulo(DisasContext *ctx)
76a66253 5289{
42a268c2 5290 TCGLabel *l1 = gen_new_label();
22e0e173
AJ
5291 TCGv_i64 t0 = tcg_temp_new_i64();
5292 TCGv_i64 t1 = tcg_temp_new_i64();
5293 TCGv t2 = tcg_temp_new();
5294 /* Start with XER OV disabled, the most likely case */
da91a00f 5295 tcg_gen_movi_tl(cpu_ov, 0);
22e0e173
AJ
5296 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
5297 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
5298 tcg_gen_mul_i64(t0, t0, t1);
5299 tcg_gen_trunc_i64_tl(t2, t0);
5300 gen_store_spr(SPR_MQ, t2);
5301 tcg_gen_shri_i64(t1, t0, 32);
5302 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
5303 tcg_gen_ext32s_i64(t1, t0);
5304 tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
da91a00f
RH
5305 tcg_gen_movi_tl(cpu_ov, 1);
5306 tcg_gen_movi_tl(cpu_so, 1);
22e0e173
AJ
5307 gen_set_label(l1);
5308 tcg_temp_free_i64(t0);
5309 tcg_temp_free_i64(t1);
5310 tcg_temp_free(t2);
76a66253 5311 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5312 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5313}
5314
5315/* nabs - nabs. */
99e300ef 5316static void gen_nabs(DisasContext *ctx)
76a66253 5317{
42a268c2
RH
5318 TCGLabel *l1 = gen_new_label();
5319 TCGLabel *l2 = gen_new_label();
22e0e173
AJ
5320 tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
5321 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5322 tcg_gen_br(l2);
5323 gen_set_label(l1);
5324 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5325 gen_set_label(l2);
76a66253 5326 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5327 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5328}
5329
5330/* nabso - nabso. */
99e300ef 5331static void gen_nabso(DisasContext *ctx)
76a66253 5332{
42a268c2
RH
5333 TCGLabel *l1 = gen_new_label();
5334 TCGLabel *l2 = gen_new_label();
22e0e173
AJ
5335 tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
5336 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5337 tcg_gen_br(l2);
5338 gen_set_label(l1);
5339 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
5340 gen_set_label(l2);
5341 /* nabs never overflows */
da91a00f 5342 tcg_gen_movi_tl(cpu_ov, 0);
76a66253 5343 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 5344 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
5345}
5346
5347/* rlmi - rlmi. */
99e300ef 5348static void gen_rlmi(DisasContext *ctx)
76a66253 5349{
7487953d
AJ
5350 uint32_t mb = MB(ctx->opcode);
5351 uint32_t me = ME(ctx->opcode);
5352 TCGv t0 = tcg_temp_new();
5353 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5354 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5355 tcg_gen_andi_tl(t0, t0, MASK(mb, me));
5356 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
5357 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
5358 tcg_temp_free(t0);
76a66253 5359 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5360 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5361}
5362
5363/* rrib - rrib. */
99e300ef 5364static void gen_rrib(DisasContext *ctx)
76a66253 5365{
7487953d
AJ
5366 TCGv t0 = tcg_temp_new();
5367 TCGv t1 = tcg_temp_new();
5368 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5369 tcg_gen_movi_tl(t1, 0x80000000);
5370 tcg_gen_shr_tl(t1, t1, t0);
5371 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5372 tcg_gen_and_tl(t0, t0, t1);
5373 tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
5374 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5375 tcg_temp_free(t0);
5376 tcg_temp_free(t1);
76a66253 5377 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5378 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5379}
5380
5381/* sle - sle. */
99e300ef 5382static void gen_sle(DisasContext *ctx)
76a66253 5383{
7487953d
AJ
5384 TCGv t0 = tcg_temp_new();
5385 TCGv t1 = tcg_temp_new();
5386 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5387 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5388 tcg_gen_subfi_tl(t1, 32, t1);
5389 tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5390 tcg_gen_or_tl(t1, t0, t1);
5391 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5392 gen_store_spr(SPR_MQ, t1);
5393 tcg_temp_free(t0);
5394 tcg_temp_free(t1);
76a66253 5395 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5396 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5397}
5398
5399/* sleq - sleq. */
99e300ef 5400static void gen_sleq(DisasContext *ctx)
76a66253 5401{
7487953d
AJ
5402 TCGv t0 = tcg_temp_new();
5403 TCGv t1 = tcg_temp_new();
5404 TCGv t2 = tcg_temp_new();
5405 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5406 tcg_gen_movi_tl(t2, 0xFFFFFFFF);
5407 tcg_gen_shl_tl(t2, t2, t0);
5408 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5409 gen_load_spr(t1, SPR_MQ);
5410 gen_store_spr(SPR_MQ, t0);
5411 tcg_gen_and_tl(t0, t0, t2);
5412 tcg_gen_andc_tl(t1, t1, t2);
5413 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5414 tcg_temp_free(t0);
5415 tcg_temp_free(t1);
5416 tcg_temp_free(t2);
76a66253 5417 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5418 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5419}
5420
5421/* sliq - sliq. */
99e300ef 5422static void gen_sliq(DisasContext *ctx)
76a66253 5423{
7487953d
AJ
5424 int sh = SH(ctx->opcode);
5425 TCGv t0 = tcg_temp_new();
5426 TCGv t1 = tcg_temp_new();
5427 tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5428 tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5429 tcg_gen_or_tl(t1, t0, t1);
5430 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5431 gen_store_spr(SPR_MQ, t1);
5432 tcg_temp_free(t0);
5433 tcg_temp_free(t1);
76a66253 5434 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5435 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5436}
5437
5438/* slliq - slliq. */
99e300ef 5439static void gen_slliq(DisasContext *ctx)
76a66253 5440{
7487953d
AJ
5441 int sh = SH(ctx->opcode);
5442 TCGv t0 = tcg_temp_new();
5443 TCGv t1 = tcg_temp_new();
5444 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5445 gen_load_spr(t1, SPR_MQ);
5446 gen_store_spr(SPR_MQ, t0);
5447 tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh));
5448 tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
5449 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5450 tcg_temp_free(t0);
5451 tcg_temp_free(t1);
76a66253 5452 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5453 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5454}
5455
5456/* sllq - sllq. */
99e300ef 5457static void gen_sllq(DisasContext *ctx)
76a66253 5458{
42a268c2
RH
5459 TCGLabel *l1 = gen_new_label();
5460 TCGLabel *l2 = gen_new_label();
7487953d
AJ
5461 TCGv t0 = tcg_temp_local_new();
5462 TCGv t1 = tcg_temp_local_new();
5463 TCGv t2 = tcg_temp_local_new();
5464 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5465 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5466 tcg_gen_shl_tl(t1, t1, t2);
5467 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5468 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5469 gen_load_spr(t0, SPR_MQ);
5470 tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5471 tcg_gen_br(l2);
5472 gen_set_label(l1);
5473 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5474 gen_load_spr(t2, SPR_MQ);
5475 tcg_gen_andc_tl(t1, t2, t1);
5476 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5477 gen_set_label(l2);
5478 tcg_temp_free(t0);
5479 tcg_temp_free(t1);
5480 tcg_temp_free(t2);
76a66253 5481 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5482 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5483}
5484
5485/* slq - slq. */
99e300ef 5486static void gen_slq(DisasContext *ctx)
76a66253 5487{
42a268c2 5488 TCGLabel *l1 = gen_new_label();
7487953d
AJ
5489 TCGv t0 = tcg_temp_new();
5490 TCGv t1 = tcg_temp_new();
5491 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5492 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5493 tcg_gen_subfi_tl(t1, 32, t1);
5494 tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5495 tcg_gen_or_tl(t1, t0, t1);
5496 gen_store_spr(SPR_MQ, t1);
5497 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5498 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5499 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5500 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5501 gen_set_label(l1);
5502 tcg_temp_free(t0);
5503 tcg_temp_free(t1);
76a66253 5504 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5505 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5506}
5507
d9bce9d9 5508/* sraiq - sraiq. */
99e300ef 5509static void gen_sraiq(DisasContext *ctx)
76a66253 5510{
7487953d 5511 int sh = SH(ctx->opcode);
42a268c2 5512 TCGLabel *l1 = gen_new_label();
7487953d
AJ
5513 TCGv t0 = tcg_temp_new();
5514 TCGv t1 = tcg_temp_new();
5515 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5516 tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5517 tcg_gen_or_tl(t0, t0, t1);
5518 gen_store_spr(SPR_MQ, t0);
da91a00f 5519 tcg_gen_movi_tl(cpu_ca, 0);
7487953d
AJ
5520 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5521 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
da91a00f 5522 tcg_gen_movi_tl(cpu_ca, 1);
7487953d
AJ
5523 gen_set_label(l1);
5524 tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
5525 tcg_temp_free(t0);
5526 tcg_temp_free(t1);
76a66253 5527 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5528 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5529}
5530
5531/* sraq - sraq. */
99e300ef 5532static void gen_sraq(DisasContext *ctx)
76a66253 5533{
42a268c2
RH
5534 TCGLabel *l1 = gen_new_label();
5535 TCGLabel *l2 = gen_new_label();
7487953d
AJ
5536 TCGv t0 = tcg_temp_new();
5537 TCGv t1 = tcg_temp_local_new();
5538 TCGv t2 = tcg_temp_local_new();
5539 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5540 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5541 tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
5542 tcg_gen_subfi_tl(t2, 32, t2);
5543 tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
5544 tcg_gen_or_tl(t0, t0, t2);
5545 gen_store_spr(SPR_MQ, t0);
5546 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5547 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
5548 tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
5549 tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
5550 gen_set_label(l1);
5551 tcg_temp_free(t0);
5552 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
da91a00f 5553 tcg_gen_movi_tl(cpu_ca, 0);
7487953d
AJ
5554 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
5555 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
da91a00f 5556 tcg_gen_movi_tl(cpu_ca, 1);
7487953d
AJ
5557 gen_set_label(l2);
5558 tcg_temp_free(t1);
5559 tcg_temp_free(t2);
76a66253 5560 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5561 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5562}
5563
5564/* sre - sre. */
99e300ef 5565static void gen_sre(DisasContext *ctx)
76a66253 5566{
7487953d
AJ
5567 TCGv t0 = tcg_temp_new();
5568 TCGv t1 = tcg_temp_new();
5569 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5570 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5571 tcg_gen_subfi_tl(t1, 32, t1);
5572 tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5573 tcg_gen_or_tl(t1, t0, t1);
5574 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5575 gen_store_spr(SPR_MQ, t1);
5576 tcg_temp_free(t0);
5577 tcg_temp_free(t1);
76a66253 5578 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5579 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5580}
5581
5582/* srea - srea. */
99e300ef 5583static void gen_srea(DisasContext *ctx)
76a66253 5584{
7487953d
AJ
5585 TCGv t0 = tcg_temp_new();
5586 TCGv t1 = tcg_temp_new();
5587 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5588 tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5589 gen_store_spr(SPR_MQ, t0);
5590 tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
5591 tcg_temp_free(t0);
5592 tcg_temp_free(t1);
76a66253 5593 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5594 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5595}
5596
5597/* sreq */
99e300ef 5598static void gen_sreq(DisasContext *ctx)
76a66253 5599{
7487953d
AJ
5600 TCGv t0 = tcg_temp_new();
5601 TCGv t1 = tcg_temp_new();
5602 TCGv t2 = tcg_temp_new();
5603 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5604 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5605 tcg_gen_shr_tl(t1, t1, t0);
5606 tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5607 gen_load_spr(t2, SPR_MQ);
5608 gen_store_spr(SPR_MQ, t0);
5609 tcg_gen_and_tl(t0, t0, t1);
5610 tcg_gen_andc_tl(t2, t2, t1);
5611 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5612 tcg_temp_free(t0);
5613 tcg_temp_free(t1);
5614 tcg_temp_free(t2);
76a66253 5615 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5616 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5617}
5618
5619/* sriq */
99e300ef 5620static void gen_sriq(DisasContext *ctx)
76a66253 5621{
7487953d
AJ
5622 int sh = SH(ctx->opcode);
5623 TCGv t0 = tcg_temp_new();
5624 TCGv t1 = tcg_temp_new();
5625 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5626 tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5627 tcg_gen_or_tl(t1, t0, t1);
5628 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5629 gen_store_spr(SPR_MQ, t1);
5630 tcg_temp_free(t0);
5631 tcg_temp_free(t1);
76a66253 5632 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5633 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5634}
5635
5636/* srliq */
99e300ef 5637static void gen_srliq(DisasContext *ctx)
76a66253 5638{
7487953d
AJ
5639 int sh = SH(ctx->opcode);
5640 TCGv t0 = tcg_temp_new();
5641 TCGv t1 = tcg_temp_new();
5642 tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5643 gen_load_spr(t1, SPR_MQ);
5644 gen_store_spr(SPR_MQ, t0);
5645 tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh));
5646 tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
5647 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5648 tcg_temp_free(t0);
5649 tcg_temp_free(t1);
76a66253 5650 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5651 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5652}
5653
5654/* srlq */
99e300ef 5655static void gen_srlq(DisasContext *ctx)
76a66253 5656{
42a268c2
RH
5657 TCGLabel *l1 = gen_new_label();
5658 TCGLabel *l2 = gen_new_label();
7487953d
AJ
5659 TCGv t0 = tcg_temp_local_new();
5660 TCGv t1 = tcg_temp_local_new();
5661 TCGv t2 = tcg_temp_local_new();
5662 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5663 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5664 tcg_gen_shr_tl(t2, t1, t2);
5665 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5666 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5667 gen_load_spr(t0, SPR_MQ);
5668 tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5669 tcg_gen_br(l2);
5670 gen_set_label(l1);
5671 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5672 tcg_gen_and_tl(t0, t0, t2);
5673 gen_load_spr(t1, SPR_MQ);
5674 tcg_gen_andc_tl(t1, t1, t2);
5675 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5676 gen_set_label(l2);
5677 tcg_temp_free(t0);
5678 tcg_temp_free(t1);
5679 tcg_temp_free(t2);
76a66253 5680 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5681 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5682}
5683
5684/* srq */
99e300ef 5685static void gen_srq(DisasContext *ctx)
76a66253 5686{
42a268c2 5687 TCGLabel *l1 = gen_new_label();
7487953d
AJ
5688 TCGv t0 = tcg_temp_new();
5689 TCGv t1 = tcg_temp_new();
5690 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5691 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5692 tcg_gen_subfi_tl(t1, 32, t1);
5693 tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5694 tcg_gen_or_tl(t1, t0, t1);
5695 gen_store_spr(SPR_MQ, t1);
5696 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5697 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5698 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5699 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5700 gen_set_label(l1);
5701 tcg_temp_free(t0);
5702 tcg_temp_free(t1);
76a66253 5703 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5704 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5705}
5706
5707/* PowerPC 602 specific instructions */
99e300ef 5708
54623277 5709/* dsa */
99e300ef 5710static void gen_dsa(DisasContext *ctx)
76a66253
JM
5711{
5712 /* XXX: TODO */
e06fcd75 5713 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5714}
5715
5716/* esa */
99e300ef 5717static void gen_esa(DisasContext *ctx)
76a66253
JM
5718{
5719 /* XXX: TODO */
e06fcd75 5720 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5721}
5722
5723/* mfrom */
99e300ef 5724static void gen_mfrom(DisasContext *ctx)
76a66253
JM
5725{
5726#if defined(CONFIG_USER_ONLY)
9b2fadda 5727 GEN_PRIV;
76a66253 5728#else
9b2fadda 5729 CHK_SV;
cf02a65c 5730 gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
9b2fadda 5731#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5732}
5733
5734/* 602 - 603 - G2 TLB management */
e8eaa2c0 5735
54623277 5736/* tlbld */
e8eaa2c0 5737static void gen_tlbld_6xx(DisasContext *ctx)
76a66253
JM
5738{
5739#if defined(CONFIG_USER_ONLY)
9b2fadda 5740 GEN_PRIV;
76a66253 5741#else
9b2fadda 5742 CHK_SV;
c6c7cf05 5743 gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9b2fadda 5744#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5745}
5746
5747/* tlbli */
e8eaa2c0 5748static void gen_tlbli_6xx(DisasContext *ctx)
76a66253
JM
5749{
5750#if defined(CONFIG_USER_ONLY)
9b2fadda 5751 GEN_PRIV;
76a66253 5752#else
9b2fadda 5753 CHK_SV;
c6c7cf05 5754 gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9b2fadda 5755#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5756}
5757
7dbe11ac 5758/* 74xx TLB management */
e8eaa2c0 5759
54623277 5760/* tlbld */
e8eaa2c0 5761static void gen_tlbld_74xx(DisasContext *ctx)
7dbe11ac
JM
5762{
5763#if defined(CONFIG_USER_ONLY)
9b2fadda 5764 GEN_PRIV;
7dbe11ac 5765#else
9b2fadda 5766 CHK_SV;
c6c7cf05 5767 gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9b2fadda 5768#endif /* defined(CONFIG_USER_ONLY) */
7dbe11ac
JM
5769}
5770
5771/* tlbli */
e8eaa2c0 5772static void gen_tlbli_74xx(DisasContext *ctx)
7dbe11ac
JM
5773{
5774#if defined(CONFIG_USER_ONLY)
9b2fadda 5775 GEN_PRIV;
7dbe11ac 5776#else
9b2fadda 5777 CHK_SV;
c6c7cf05 5778 gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9b2fadda 5779#endif /* defined(CONFIG_USER_ONLY) */
7dbe11ac
JM
5780}
5781
76a66253 5782/* POWER instructions not in PowerPC 601 */
99e300ef 5783
54623277 5784/* clf */
99e300ef 5785static void gen_clf(DisasContext *ctx)
76a66253
JM
5786{
5787 /* Cache line flush: implemented as no-op */
5788}
5789
5790/* cli */
99e300ef 5791static void gen_cli(DisasContext *ctx)
76a66253 5792{
76a66253 5793#if defined(CONFIG_USER_ONLY)
9b2fadda 5794 GEN_PRIV;
76a66253 5795#else
9b2fadda
BH
5796 /* Cache line invalidate: privileged and treated as no-op */
5797 CHK_SV;
5798#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5799}
5800
5801/* dclst */
99e300ef 5802static void gen_dclst(DisasContext *ctx)
76a66253
JM
5803{
5804 /* Data cache line store: treated as no-op */
5805}
5806
99e300ef 5807static void gen_mfsri(DisasContext *ctx)
76a66253
JM
5808{
5809#if defined(CONFIG_USER_ONLY)
9b2fadda 5810 GEN_PRIV;
76a66253 5811#else
74d37793
AJ
5812 int ra = rA(ctx->opcode);
5813 int rd = rD(ctx->opcode);
5814 TCGv t0;
9b2fadda
BH
5815
5816 CHK_SV;
74d37793 5817 t0 = tcg_temp_new();
76db3ba4 5818 gen_addr_reg_index(ctx, t0);
74d37793
AJ
5819 tcg_gen_shri_tl(t0, t0, 28);
5820 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 5821 gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
74d37793 5822 tcg_temp_free(t0);
76a66253 5823 if (ra != 0 && ra != rd)
74d37793 5824 tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
9b2fadda 5825#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5826}
5827
99e300ef 5828static void gen_rac(DisasContext *ctx)
76a66253
JM
5829{
5830#if defined(CONFIG_USER_ONLY)
9b2fadda 5831 GEN_PRIV;
76a66253 5832#else
22e0e173 5833 TCGv t0;
9b2fadda
BH
5834
5835 CHK_SV;
22e0e173 5836 t0 = tcg_temp_new();
76db3ba4 5837 gen_addr_reg_index(ctx, t0);
c6c7cf05 5838 gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
22e0e173 5839 tcg_temp_free(t0);
9b2fadda 5840#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5841}
5842
99e300ef 5843static void gen_rfsvc(DisasContext *ctx)
76a66253
JM
5844{
5845#if defined(CONFIG_USER_ONLY)
9b2fadda 5846 GEN_PRIV;
76a66253 5847#else
9b2fadda
BH
5848 CHK_SV;
5849
e5f17ac6 5850 gen_helper_rfsvc(cpu_env);
e06fcd75 5851 gen_sync_exception(ctx);
9b2fadda 5852#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5853}
5854
5855/* svc is not implemented for now */
5856
5857/* POWER2 specific instructions */
5858/* Quad manipulation (load/store two floats at a time) */
76a66253
JM
5859
5860/* lfq */
99e300ef 5861static void gen_lfq(DisasContext *ctx)
76a66253 5862{
01a4afeb 5863 int rd = rD(ctx->opcode);
76db3ba4
AJ
5864 TCGv t0;
5865 gen_set_access_type(ctx, ACCESS_FLOAT);
5866 t0 = tcg_temp_new();
5867 gen_addr_imm_index(ctx, t0, 0);
5868 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5869 gen_addr_add(ctx, t0, t0, 8);
5870 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5871 tcg_temp_free(t0);
76a66253
JM
5872}
5873
5874/* lfqu */
99e300ef 5875static void gen_lfqu(DisasContext *ctx)
76a66253
JM
5876{
5877 int ra = rA(ctx->opcode);
01a4afeb 5878 int rd = rD(ctx->opcode);
76db3ba4
AJ
5879 TCGv t0, t1;
5880 gen_set_access_type(ctx, ACCESS_FLOAT);
5881 t0 = tcg_temp_new();
5882 t1 = tcg_temp_new();
5883 gen_addr_imm_index(ctx, t0, 0);
5884 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5885 gen_addr_add(ctx, t1, t0, 8);
5886 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
76a66253 5887 if (ra != 0)
01a4afeb
AJ
5888 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5889 tcg_temp_free(t0);
5890 tcg_temp_free(t1);
76a66253
JM
5891}
5892
5893/* lfqux */
99e300ef 5894static void gen_lfqux(DisasContext *ctx)
76a66253
JM
5895{
5896 int ra = rA(ctx->opcode);
01a4afeb 5897 int rd = rD(ctx->opcode);
76db3ba4
AJ
5898 gen_set_access_type(ctx, ACCESS_FLOAT);
5899 TCGv t0, t1;
5900 t0 = tcg_temp_new();
5901 gen_addr_reg_index(ctx, t0);
5902 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5903 t1 = tcg_temp_new();
5904 gen_addr_add(ctx, t1, t0, 8);
5905 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5906 tcg_temp_free(t1);
76a66253 5907 if (ra != 0)
01a4afeb
AJ
5908 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5909 tcg_temp_free(t0);
76a66253
JM
5910}
5911
5912/* lfqx */
99e300ef 5913static void gen_lfqx(DisasContext *ctx)
76a66253 5914{
01a4afeb 5915 int rd = rD(ctx->opcode);
76db3ba4
AJ
5916 TCGv t0;
5917 gen_set_access_type(ctx, ACCESS_FLOAT);
5918 t0 = tcg_temp_new();
5919 gen_addr_reg_index(ctx, t0);
5920 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5921 gen_addr_add(ctx, t0, t0, 8);
5922 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5923 tcg_temp_free(t0);
76a66253
JM
5924}
5925
5926/* stfq */
99e300ef 5927static void gen_stfq(DisasContext *ctx)
76a66253 5928{
01a4afeb 5929 int rd = rD(ctx->opcode);
76db3ba4
AJ
5930 TCGv t0;
5931 gen_set_access_type(ctx, ACCESS_FLOAT);
5932 t0 = tcg_temp_new();
5933 gen_addr_imm_index(ctx, t0, 0);
5934 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5935 gen_addr_add(ctx, t0, t0, 8);
5936 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5937 tcg_temp_free(t0);
76a66253
JM
5938}
5939
5940/* stfqu */
99e300ef 5941static void gen_stfqu(DisasContext *ctx)
76a66253
JM
5942{
5943 int ra = rA(ctx->opcode);
01a4afeb 5944 int rd = rD(ctx->opcode);
76db3ba4
AJ
5945 TCGv t0, t1;
5946 gen_set_access_type(ctx, ACCESS_FLOAT);
5947 t0 = tcg_temp_new();
5948 gen_addr_imm_index(ctx, t0, 0);
5949 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5950 t1 = tcg_temp_new();
5951 gen_addr_add(ctx, t1, t0, 8);
5952 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5953 tcg_temp_free(t1);
76a66253 5954 if (ra != 0)
01a4afeb
AJ
5955 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5956 tcg_temp_free(t0);
76a66253
JM
5957}
5958
5959/* stfqux */
99e300ef 5960static void gen_stfqux(DisasContext *ctx)
76a66253
JM
5961{
5962 int ra = rA(ctx->opcode);
01a4afeb 5963 int rd = rD(ctx->opcode);
76db3ba4
AJ
5964 TCGv t0, t1;
5965 gen_set_access_type(ctx, ACCESS_FLOAT);
5966 t0 = tcg_temp_new();
5967 gen_addr_reg_index(ctx, t0);
5968 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5969 t1 = tcg_temp_new();
5970 gen_addr_add(ctx, t1, t0, 8);
5971 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5972 tcg_temp_free(t1);
76a66253 5973 if (ra != 0)
01a4afeb
AJ
5974 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5975 tcg_temp_free(t0);
76a66253
JM
5976}
5977
5978/* stfqx */
99e300ef 5979static void gen_stfqx(DisasContext *ctx)
76a66253 5980{
01a4afeb 5981 int rd = rD(ctx->opcode);
76db3ba4
AJ
5982 TCGv t0;
5983 gen_set_access_type(ctx, ACCESS_FLOAT);
5984 t0 = tcg_temp_new();
5985 gen_addr_reg_index(ctx, t0);
5986 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5987 gen_addr_add(ctx, t0, t0, 8);
5988 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5989 tcg_temp_free(t0);
76a66253
JM
5990}
5991
5992/* BookE specific instructions */
99e300ef 5993
54623277 5994/* XXX: not implemented on 440 ? */
99e300ef 5995static void gen_mfapidi(DisasContext *ctx)
76a66253
JM
5996{
5997 /* XXX: TODO */
e06fcd75 5998 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5999}
6000
2662a059 6001/* XXX: not implemented on 440 ? */
99e300ef 6002static void gen_tlbiva(DisasContext *ctx)
76a66253
JM
6003{
6004#if defined(CONFIG_USER_ONLY)
9b2fadda 6005 GEN_PRIV;
76a66253 6006#else
74d37793 6007 TCGv t0;
9b2fadda
BH
6008
6009 CHK_SV;
ec72e276 6010 t0 = tcg_temp_new();
76db3ba4 6011 gen_addr_reg_index(ctx, t0);
4693364f 6012 gen_helper_tlbiva(cpu_env, cpu_gpr[rB(ctx->opcode)]);
74d37793 6013 tcg_temp_free(t0);
9b2fadda 6014#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6015}
6016
6017/* All 405 MAC instructions are translated here */
636aa200
BS
6018static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
6019 int ra, int rb, int rt, int Rc)
76a66253 6020{
182608d4
AJ
6021 TCGv t0, t1;
6022
a7812ae4
PB
6023 t0 = tcg_temp_local_new();
6024 t1 = tcg_temp_local_new();
182608d4 6025
76a66253
JM
6026 switch (opc3 & 0x0D) {
6027 case 0x05:
6028 /* macchw - macchw. - macchwo - macchwo. */
6029 /* macchws - macchws. - macchwso - macchwso. */
6030 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
6031 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
6032 /* mulchw - mulchw. */
182608d4
AJ
6033 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
6034 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
6035 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
6036 break;
6037 case 0x04:
6038 /* macchwu - macchwu. - macchwuo - macchwuo. */
6039 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
6040 /* mulchwu - mulchwu. */
182608d4
AJ
6041 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
6042 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
6043 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
6044 break;
6045 case 0x01:
6046 /* machhw - machhw. - machhwo - machhwo. */
6047 /* machhws - machhws. - machhwso - machhwso. */
6048 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
6049 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
6050 /* mulhhw - mulhhw. */
182608d4
AJ
6051 tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
6052 tcg_gen_ext16s_tl(t0, t0);
6053 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
6054 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
6055 break;
6056 case 0x00:
6057 /* machhwu - machhwu. - machhwuo - machhwuo. */
6058 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
6059 /* mulhhwu - mulhhwu. */
182608d4
AJ
6060 tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
6061 tcg_gen_ext16u_tl(t0, t0);
6062 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
6063 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
6064 break;
6065 case 0x0D:
6066 /* maclhw - maclhw. - maclhwo - maclhwo. */
6067 /* maclhws - maclhws. - maclhwso - maclhwso. */
6068 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
6069 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
6070 /* mullhw - mullhw. */
182608d4
AJ
6071 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
6072 tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
76a66253
JM
6073 break;
6074 case 0x0C:
6075 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
6076 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
6077 /* mullhwu - mullhwu. */
182608d4
AJ
6078 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
6079 tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
76a66253
JM
6080 break;
6081 }
76a66253 6082 if (opc2 & 0x04) {
182608d4
AJ
6083 /* (n)multiply-and-accumulate (0x0C / 0x0E) */
6084 tcg_gen_mul_tl(t1, t0, t1);
6085 if (opc2 & 0x02) {
6086 /* nmultiply-and-accumulate (0x0E) */
6087 tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
6088 } else {
6089 /* multiply-and-accumulate (0x0C) */
6090 tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
6091 }
6092
6093 if (opc3 & 0x12) {
6094 /* Check overflow and/or saturate */
42a268c2 6095 TCGLabel *l1 = gen_new_label();
182608d4
AJ
6096
6097 if (opc3 & 0x10) {
6098 /* Start with XER OV disabled, the most likely case */
da91a00f 6099 tcg_gen_movi_tl(cpu_ov, 0);
182608d4
AJ
6100 }
6101 if (opc3 & 0x01) {
6102 /* Signed */
6103 tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
6104 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
6105 tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
6106 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
bdc4e053 6107 if (opc3 & 0x02) {
182608d4
AJ
6108 /* Saturate */
6109 tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
6110 tcg_gen_xori_tl(t0, t0, 0x7fffffff);
6111 }
6112 } else {
6113 /* Unsigned */
6114 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
bdc4e053 6115 if (opc3 & 0x02) {
182608d4
AJ
6116 /* Saturate */
6117 tcg_gen_movi_tl(t0, UINT32_MAX);
6118 }
6119 }
6120 if (opc3 & 0x10) {
6121 /* Check overflow */
da91a00f
RH
6122 tcg_gen_movi_tl(cpu_ov, 1);
6123 tcg_gen_movi_tl(cpu_so, 1);
182608d4
AJ
6124 }
6125 gen_set_label(l1);
6126 tcg_gen_mov_tl(cpu_gpr[rt], t0);
6127 }
6128 } else {
6129 tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
76a66253 6130 }
182608d4
AJ
6131 tcg_temp_free(t0);
6132 tcg_temp_free(t1);
76a66253
JM
6133 if (unlikely(Rc) != 0) {
6134 /* Update Rc0 */
182608d4 6135 gen_set_Rc0(ctx, cpu_gpr[rt]);
76a66253
JM
6136 }
6137}
6138
a750fc0b 6139#define GEN_MAC_HANDLER(name, opc2, opc3) \
99e300ef 6140static void glue(gen_, name)(DisasContext *ctx) \
76a66253
JM
6141{ \
6142 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
6143 rD(ctx->opcode), Rc(ctx->opcode)); \
6144}
6145
6146/* macchw - macchw. */
a750fc0b 6147GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
76a66253 6148/* macchwo - macchwo. */
a750fc0b 6149GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
76a66253 6150/* macchws - macchws. */
a750fc0b 6151GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
76a66253 6152/* macchwso - macchwso. */
a750fc0b 6153GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
76a66253 6154/* macchwsu - macchwsu. */
a750fc0b 6155GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
76a66253 6156/* macchwsuo - macchwsuo. */
a750fc0b 6157GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
76a66253 6158/* macchwu - macchwu. */
a750fc0b 6159GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
76a66253 6160/* macchwuo - macchwuo. */
a750fc0b 6161GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
76a66253 6162/* machhw - machhw. */
a750fc0b 6163GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
76a66253 6164/* machhwo - machhwo. */
a750fc0b 6165GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
76a66253 6166/* machhws - machhws. */
a750fc0b 6167GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
76a66253 6168/* machhwso - machhwso. */
a750fc0b 6169GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
76a66253 6170/* machhwsu - machhwsu. */
a750fc0b 6171GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
76a66253 6172/* machhwsuo - machhwsuo. */
a750fc0b 6173GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
76a66253 6174/* machhwu - machhwu. */
a750fc0b 6175GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
76a66253 6176/* machhwuo - machhwuo. */
a750fc0b 6177GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
76a66253 6178/* maclhw - maclhw. */
a750fc0b 6179GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
76a66253 6180/* maclhwo - maclhwo. */
a750fc0b 6181GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
76a66253 6182/* maclhws - maclhws. */
a750fc0b 6183GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
76a66253 6184/* maclhwso - maclhwso. */
a750fc0b 6185GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
76a66253 6186/* maclhwu - maclhwu. */
a750fc0b 6187GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
76a66253 6188/* maclhwuo - maclhwuo. */
a750fc0b 6189GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
76a66253 6190/* maclhwsu - maclhwsu. */
a750fc0b 6191GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
76a66253 6192/* maclhwsuo - maclhwsuo. */
a750fc0b 6193GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
76a66253 6194/* nmacchw - nmacchw. */
a750fc0b 6195GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
76a66253 6196/* nmacchwo - nmacchwo. */
a750fc0b 6197GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
76a66253 6198/* nmacchws - nmacchws. */
a750fc0b 6199GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
76a66253 6200/* nmacchwso - nmacchwso. */
a750fc0b 6201GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
76a66253 6202/* nmachhw - nmachhw. */
a750fc0b 6203GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
76a66253 6204/* nmachhwo - nmachhwo. */
a750fc0b 6205GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
76a66253 6206/* nmachhws - nmachhws. */
a750fc0b 6207GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
76a66253 6208/* nmachhwso - nmachhwso. */
a750fc0b 6209GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
76a66253 6210/* nmaclhw - nmaclhw. */
a750fc0b 6211GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
76a66253 6212/* nmaclhwo - nmaclhwo. */
a750fc0b 6213GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
76a66253 6214/* nmaclhws - nmaclhws. */
a750fc0b 6215GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
76a66253 6216/* nmaclhwso - nmaclhwso. */
a750fc0b 6217GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
76a66253
JM
6218
6219/* mulchw - mulchw. */
a750fc0b 6220GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
76a66253 6221/* mulchwu - mulchwu. */
a750fc0b 6222GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
76a66253 6223/* mulhhw - mulhhw. */
a750fc0b 6224GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
76a66253 6225/* mulhhwu - mulhhwu. */
a750fc0b 6226GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
76a66253 6227/* mullhw - mullhw. */
a750fc0b 6228GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
76a66253 6229/* mullhwu - mullhwu. */
a750fc0b 6230GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
76a66253
JM
6231
6232/* mfdcr */
99e300ef 6233static void gen_mfdcr(DisasContext *ctx)
76a66253
JM
6234{
6235#if defined(CONFIG_USER_ONLY)
9b2fadda 6236 GEN_PRIV;
76a66253 6237#else
06dca6a7 6238 TCGv dcrn;
9b2fadda
BH
6239
6240 CHK_SV;
06dca6a7
AJ
6241 /* NIP cannot be restored if the memory exception comes from an helper */
6242 gen_update_nip(ctx, ctx->nip - 4);
6243 dcrn = tcg_const_tl(SPR(ctx->opcode));
d0f1562d 6244 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
06dca6a7 6245 tcg_temp_free(dcrn);
9b2fadda 6246#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6247}
6248
6249/* mtdcr */
99e300ef 6250static void gen_mtdcr(DisasContext *ctx)
76a66253
JM
6251{
6252#if defined(CONFIG_USER_ONLY)
9b2fadda 6253 GEN_PRIV;
76a66253 6254#else
06dca6a7 6255 TCGv dcrn;
9b2fadda
BH
6256
6257 CHK_SV;
06dca6a7
AJ
6258 /* NIP cannot be restored if the memory exception comes from an helper */
6259 gen_update_nip(ctx, ctx->nip - 4);
6260 dcrn = tcg_const_tl(SPR(ctx->opcode));
d0f1562d 6261 gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
06dca6a7 6262 tcg_temp_free(dcrn);
9b2fadda 6263#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc
JM
6264}
6265
6266/* mfdcrx */
2662a059 6267/* XXX: not implemented on 440 ? */
99e300ef 6268static void gen_mfdcrx(DisasContext *ctx)
a42bd6cc
JM
6269{
6270#if defined(CONFIG_USER_ONLY)
9b2fadda 6271 GEN_PRIV;
a42bd6cc 6272#else
9b2fadda 6273 CHK_SV;
06dca6a7
AJ
6274 /* NIP cannot be restored if the memory exception comes from an helper */
6275 gen_update_nip(ctx, ctx->nip - 4);
d0f1562d
BS
6276 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
6277 cpu_gpr[rA(ctx->opcode)]);
a750fc0b 6278 /* Note: Rc update flag set leads to undefined state of Rc0 */
9b2fadda 6279#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc
JM
6280}
6281
6282/* mtdcrx */
2662a059 6283/* XXX: not implemented on 440 ? */
99e300ef 6284static void gen_mtdcrx(DisasContext *ctx)
a42bd6cc
JM
6285{
6286#if defined(CONFIG_USER_ONLY)
9b2fadda 6287 GEN_PRIV;
a42bd6cc 6288#else
9b2fadda 6289 CHK_SV;
06dca6a7
AJ
6290 /* NIP cannot be restored if the memory exception comes from an helper */
6291 gen_update_nip(ctx, ctx->nip - 4);
d0f1562d
BS
6292 gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
6293 cpu_gpr[rS(ctx->opcode)]);
a750fc0b 6294 /* Note: Rc update flag set leads to undefined state of Rc0 */
9b2fadda 6295#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6296}
6297
a750fc0b 6298/* mfdcrux (PPC 460) : user-mode access to DCR */
99e300ef 6299static void gen_mfdcrux(DisasContext *ctx)
a750fc0b 6300{
06dca6a7
AJ
6301 /* NIP cannot be restored if the memory exception comes from an helper */
6302 gen_update_nip(ctx, ctx->nip - 4);
d0f1562d
BS
6303 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
6304 cpu_gpr[rA(ctx->opcode)]);
a750fc0b
JM
6305 /* Note: Rc update flag set leads to undefined state of Rc0 */
6306}
6307
6308/* mtdcrux (PPC 460) : user-mode access to DCR */
99e300ef 6309static void gen_mtdcrux(DisasContext *ctx)
a750fc0b 6310{
06dca6a7
AJ
6311 /* NIP cannot be restored if the memory exception comes from an helper */
6312 gen_update_nip(ctx, ctx->nip - 4);
975e5463 6313 gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
d0f1562d 6314 cpu_gpr[rS(ctx->opcode)]);
a750fc0b
JM
6315 /* Note: Rc update flag set leads to undefined state of Rc0 */
6316}
6317
76a66253 6318/* dccci */
99e300ef 6319static void gen_dccci(DisasContext *ctx)
76a66253 6320{
9b2fadda 6321 CHK_SV;
76a66253 6322 /* interpreted as no-op */
76a66253
JM
6323}
6324
6325/* dcread */
99e300ef 6326static void gen_dcread(DisasContext *ctx)
76a66253
JM
6327{
6328#if defined(CONFIG_USER_ONLY)
9b2fadda 6329 GEN_PRIV;
76a66253 6330#else
b61f2753 6331 TCGv EA, val;
9b2fadda
BH
6332
6333 CHK_SV;
76db3ba4 6334 gen_set_access_type(ctx, ACCESS_CACHE);
a7812ae4 6335 EA = tcg_temp_new();
76db3ba4 6336 gen_addr_reg_index(ctx, EA);
a7812ae4 6337 val = tcg_temp_new();
76db3ba4 6338 gen_qemu_ld32u(ctx, val, EA);
b61f2753
AJ
6339 tcg_temp_free(val);
6340 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
6341 tcg_temp_free(EA);
9b2fadda 6342#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6343}
6344
6345/* icbt */
e8eaa2c0 6346static void gen_icbt_40x(DisasContext *ctx)
76a66253
JM
6347{
6348 /* interpreted as no-op */
6349 /* XXX: specification say this is treated as a load by the MMU
6350 * but does not generate any exception
6351 */
6352}
6353
6354/* iccci */
99e300ef 6355static void gen_iccci(DisasContext *ctx)
76a66253 6356{
9b2fadda 6357 CHK_SV;
76a66253 6358 /* interpreted as no-op */
76a66253
JM
6359}
6360
6361/* icread */
99e300ef 6362static void gen_icread(DisasContext *ctx)
76a66253 6363{
9b2fadda 6364 CHK_SV;
76a66253 6365 /* interpreted as no-op */
76a66253
JM
6366}
6367
c47493f2 6368/* rfci (supervisor only) */
e8eaa2c0 6369static void gen_rfci_40x(DisasContext *ctx)
a42bd6cc
JM
6370{
6371#if defined(CONFIG_USER_ONLY)
9b2fadda 6372 GEN_PRIV;
a42bd6cc 6373#else
9b2fadda 6374 CHK_SV;
a42bd6cc 6375 /* Restore CPU state */
e5f17ac6 6376 gen_helper_40x_rfci(cpu_env);
e06fcd75 6377 gen_sync_exception(ctx);
9b2fadda 6378#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc
JM
6379}
6380
99e300ef 6381static void gen_rfci(DisasContext *ctx)
a42bd6cc
JM
6382{
6383#if defined(CONFIG_USER_ONLY)
9b2fadda 6384 GEN_PRIV;
a42bd6cc 6385#else
9b2fadda 6386 CHK_SV;
a42bd6cc 6387 /* Restore CPU state */
e5f17ac6 6388 gen_helper_rfci(cpu_env);
e06fcd75 6389 gen_sync_exception(ctx);
9b2fadda 6390#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc
JM
6391}
6392
6393/* BookE specific */
99e300ef 6394
54623277 6395/* XXX: not implemented on 440 ? */
99e300ef 6396static void gen_rfdi(DisasContext *ctx)
76a66253
JM
6397{
6398#if defined(CONFIG_USER_ONLY)
9b2fadda 6399 GEN_PRIV;
76a66253 6400#else
9b2fadda 6401 CHK_SV;
76a66253 6402 /* Restore CPU state */
e5f17ac6 6403 gen_helper_rfdi(cpu_env);
e06fcd75 6404 gen_sync_exception(ctx);
9b2fadda 6405#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6406}
6407
2662a059 6408/* XXX: not implemented on 440 ? */
99e300ef 6409static void gen_rfmci(DisasContext *ctx)
a42bd6cc
JM
6410{
6411#if defined(CONFIG_USER_ONLY)
9b2fadda 6412 GEN_PRIV;
a42bd6cc 6413#else
9b2fadda 6414 CHK_SV;
a42bd6cc 6415 /* Restore CPU state */
e5f17ac6 6416 gen_helper_rfmci(cpu_env);
e06fcd75 6417 gen_sync_exception(ctx);
9b2fadda 6418#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc 6419}
5eb7995e 6420
d9bce9d9 6421/* TLB management - PowerPC 405 implementation */
e8eaa2c0 6422
54623277 6423/* tlbre */
e8eaa2c0 6424static void gen_tlbre_40x(DisasContext *ctx)
76a66253
JM
6425{
6426#if defined(CONFIG_USER_ONLY)
9b2fadda 6427 GEN_PRIV;
76a66253 6428#else
9b2fadda 6429 CHK_SV;
76a66253
JM
6430 switch (rB(ctx->opcode)) {
6431 case 0:
c6c7cf05
BS
6432 gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
6433 cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
6434 break;
6435 case 1:
c6c7cf05
BS
6436 gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
6437 cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
6438 break;
6439 default:
e06fcd75 6440 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253 6441 break;
9a64fbe4 6442 }
9b2fadda 6443#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6444}
6445
d9bce9d9 6446/* tlbsx - tlbsx. */
e8eaa2c0 6447static void gen_tlbsx_40x(DisasContext *ctx)
76a66253
JM
6448{
6449#if defined(CONFIG_USER_ONLY)
9b2fadda 6450 GEN_PRIV;
76a66253 6451#else
74d37793 6452 TCGv t0;
9b2fadda
BH
6453
6454 CHK_SV;
74d37793 6455 t0 = tcg_temp_new();
76db3ba4 6456 gen_addr_reg_index(ctx, t0);
c6c7cf05 6457 gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793
AJ
6458 tcg_temp_free(t0);
6459 if (Rc(ctx->opcode)) {
42a268c2 6460 TCGLabel *l1 = gen_new_label();
da91a00f 6461 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
74d37793
AJ
6462 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6463 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6464 gen_set_label(l1);
6465 }
9b2fadda 6466#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
6467}
6468
76a66253 6469/* tlbwe */
e8eaa2c0 6470static void gen_tlbwe_40x(DisasContext *ctx)
79aceca5 6471{
76a66253 6472#if defined(CONFIG_USER_ONLY)
9b2fadda 6473 GEN_PRIV;
76a66253 6474#else
9b2fadda
BH
6475 CHK_SV;
6476
76a66253
JM
6477 switch (rB(ctx->opcode)) {
6478 case 0:
c6c7cf05
BS
6479 gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
6480 cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
6481 break;
6482 case 1:
c6c7cf05
BS
6483 gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
6484 cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
6485 break;
6486 default:
e06fcd75 6487 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253 6488 break;
9a64fbe4 6489 }
9b2fadda 6490#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6491}
6492
a4bb6c3e 6493/* TLB management - PowerPC 440 implementation */
e8eaa2c0 6494
54623277 6495/* tlbre */
e8eaa2c0 6496static void gen_tlbre_440(DisasContext *ctx)
5eb7995e
JM
6497{
6498#if defined(CONFIG_USER_ONLY)
9b2fadda 6499 GEN_PRIV;
5eb7995e 6500#else
9b2fadda
BH
6501 CHK_SV;
6502
5eb7995e
JM
6503 switch (rB(ctx->opcode)) {
6504 case 0:
5eb7995e 6505 case 1:
5eb7995e 6506 case 2:
74d37793
AJ
6507 {
6508 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
c6c7cf05
BS
6509 gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
6510 t0, cpu_gpr[rA(ctx->opcode)]);
74d37793
AJ
6511 tcg_temp_free_i32(t0);
6512 }
5eb7995e
JM
6513 break;
6514 default:
e06fcd75 6515 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5eb7995e
JM
6516 break;
6517 }
9b2fadda 6518#endif /* defined(CONFIG_USER_ONLY) */
5eb7995e
JM
6519}
6520
6521/* tlbsx - tlbsx. */
e8eaa2c0 6522static void gen_tlbsx_440(DisasContext *ctx)
5eb7995e
JM
6523{
6524#if defined(CONFIG_USER_ONLY)
9b2fadda 6525 GEN_PRIV;
5eb7995e 6526#else
74d37793 6527 TCGv t0;
9b2fadda
BH
6528
6529 CHK_SV;
74d37793 6530 t0 = tcg_temp_new();
76db3ba4 6531 gen_addr_reg_index(ctx, t0);
c6c7cf05 6532 gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793
AJ
6533 tcg_temp_free(t0);
6534 if (Rc(ctx->opcode)) {
42a268c2 6535 TCGLabel *l1 = gen_new_label();
da91a00f 6536 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
74d37793
AJ
6537 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6538 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6539 gen_set_label(l1);
6540 }
9b2fadda 6541#endif /* defined(CONFIG_USER_ONLY) */
5eb7995e
JM
6542}
6543
6544/* tlbwe */
e8eaa2c0 6545static void gen_tlbwe_440(DisasContext *ctx)
5eb7995e
JM
6546{
6547#if defined(CONFIG_USER_ONLY)
9b2fadda 6548 GEN_PRIV;
5eb7995e 6549#else
9b2fadda 6550 CHK_SV;
5eb7995e
JM
6551 switch (rB(ctx->opcode)) {
6552 case 0:
5eb7995e 6553 case 1:
5eb7995e 6554 case 2:
74d37793
AJ
6555 {
6556 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
c6c7cf05
BS
6557 gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
6558 cpu_gpr[rS(ctx->opcode)]);
74d37793
AJ
6559 tcg_temp_free_i32(t0);
6560 }
5eb7995e
JM
6561 break;
6562 default:
e06fcd75 6563 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5eb7995e
JM
6564 break;
6565 }
9b2fadda 6566#endif /* defined(CONFIG_USER_ONLY) */
5eb7995e
JM
6567}
6568
01662f3e
AG
6569/* TLB management - PowerPC BookE 2.06 implementation */
6570
6571/* tlbre */
6572static void gen_tlbre_booke206(DisasContext *ctx)
6573{
9b2fadda
BH
6574 #if defined(CONFIG_USER_ONLY)
6575 GEN_PRIV;
01662f3e 6576#else
9b2fadda 6577 CHK_SV;
c6c7cf05 6578 gen_helper_booke206_tlbre(cpu_env);
9b2fadda 6579#endif /* defined(CONFIG_USER_ONLY) */
01662f3e
AG
6580}
6581
6582/* tlbsx - tlbsx. */
6583static void gen_tlbsx_booke206(DisasContext *ctx)
6584{
6585#if defined(CONFIG_USER_ONLY)
9b2fadda 6586 GEN_PRIV;
01662f3e
AG
6587#else
6588 TCGv t0;
01662f3e 6589
9b2fadda 6590 CHK_SV;
01662f3e
AG
6591 if (rA(ctx->opcode)) {
6592 t0 = tcg_temp_new();
6593 tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
6594 } else {
6595 t0 = tcg_const_tl(0);
6596 }
6597
6598 tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
c6c7cf05 6599 gen_helper_booke206_tlbsx(cpu_env, t0);
c80d1df5 6600 tcg_temp_free(t0);
9b2fadda 6601#endif /* defined(CONFIG_USER_ONLY) */
01662f3e
AG
6602}
6603
6604/* tlbwe */
6605static void gen_tlbwe_booke206(DisasContext *ctx)
6606{
6607#if defined(CONFIG_USER_ONLY)
9b2fadda 6608 GEN_PRIV;
01662f3e 6609#else
9b2fadda 6610 CHK_SV;
3f162d11 6611 gen_update_nip(ctx, ctx->nip - 4);
c6c7cf05 6612 gen_helper_booke206_tlbwe(cpu_env);
9b2fadda 6613#endif /* defined(CONFIG_USER_ONLY) */
01662f3e
AG
6614}
6615
6616static void gen_tlbivax_booke206(DisasContext *ctx)
6617{
6618#if defined(CONFIG_USER_ONLY)
9b2fadda 6619 GEN_PRIV;
01662f3e
AG
6620#else
6621 TCGv t0;
01662f3e 6622
9b2fadda 6623 CHK_SV;
01662f3e
AG
6624 t0 = tcg_temp_new();
6625 gen_addr_reg_index(ctx, t0);
c6c7cf05 6626 gen_helper_booke206_tlbivax(cpu_env, t0);
c80d1df5 6627 tcg_temp_free(t0);
9b2fadda 6628#endif /* defined(CONFIG_USER_ONLY) */
01662f3e
AG
6629}
6630
6d3db821
AG
6631static void gen_tlbilx_booke206(DisasContext *ctx)
6632{
6633#if defined(CONFIG_USER_ONLY)
9b2fadda 6634 GEN_PRIV;
6d3db821
AG
6635#else
6636 TCGv t0;
6d3db821 6637
9b2fadda 6638 CHK_SV;
6d3db821
AG
6639 t0 = tcg_temp_new();
6640 gen_addr_reg_index(ctx, t0);
6641
6642 switch((ctx->opcode >> 21) & 0x3) {
6643 case 0:
c6c7cf05 6644 gen_helper_booke206_tlbilx0(cpu_env, t0);
6d3db821
AG
6645 break;
6646 case 1:
c6c7cf05 6647 gen_helper_booke206_tlbilx1(cpu_env, t0);
6d3db821
AG
6648 break;
6649 case 3:
c6c7cf05 6650 gen_helper_booke206_tlbilx3(cpu_env, t0);
6d3db821
AG
6651 break;
6652 default:
6653 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6654 break;
6655 }
6656
6657 tcg_temp_free(t0);
9b2fadda 6658#endif /* defined(CONFIG_USER_ONLY) */
6d3db821
AG
6659}
6660
01662f3e 6661
76a66253 6662/* wrtee */
99e300ef 6663static void gen_wrtee(DisasContext *ctx)
76a66253
JM
6664{
6665#if defined(CONFIG_USER_ONLY)
9b2fadda 6666 GEN_PRIV;
76a66253 6667#else
6527f6ea 6668 TCGv t0;
9b2fadda
BH
6669
6670 CHK_SV;
6527f6ea
AJ
6671 t0 = tcg_temp_new();
6672 tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6673 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6674 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6675 tcg_temp_free(t0);
dee96f6c
JM
6676 /* Stop translation to have a chance to raise an exception
6677 * if we just set msr_ee to 1
6678 */
e06fcd75 6679 gen_stop_exception(ctx);
9b2fadda 6680#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6681}
6682
6683/* wrteei */
99e300ef 6684static void gen_wrteei(DisasContext *ctx)
76a66253
JM
6685{
6686#if defined(CONFIG_USER_ONLY)
9b2fadda 6687 GEN_PRIV;
76a66253 6688#else
9b2fadda 6689 CHK_SV;
fbe73008 6690 if (ctx->opcode & 0x00008000) {
6527f6ea
AJ
6691 tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6692 /* Stop translation to have a chance to raise an exception */
e06fcd75 6693 gen_stop_exception(ctx);
6527f6ea 6694 } else {
1b6e5f99 6695 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6527f6ea 6696 }
9b2fadda 6697#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6698}
6699
08e46e54 6700/* PowerPC 440 specific instructions */
99e300ef 6701
54623277 6702/* dlmzb */
99e300ef 6703static void gen_dlmzb(DisasContext *ctx)
76a66253 6704{
ef0d51af 6705 TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
d15f74fb
BS
6706 gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
6707 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
ef0d51af 6708 tcg_temp_free_i32(t0);
76a66253
JM
6709}
6710
6711/* mbar replaces eieio on 440 */
99e300ef 6712static void gen_mbar(DisasContext *ctx)
76a66253
JM
6713{
6714 /* interpreted as no-op */
6715}
6716
6717/* msync replaces sync on 440 */
dcb2b9e1 6718static void gen_msync_4xx(DisasContext *ctx)
76a66253
JM
6719{
6720 /* interpreted as no-op */
6721}
6722
6723/* icbt */
e8eaa2c0 6724static void gen_icbt_440(DisasContext *ctx)
76a66253
JM
6725{
6726 /* interpreted as no-op */
6727 /* XXX: specification say this is treated as a load by the MMU
6728 * but does not generate any exception
6729 */
79aceca5
FB
6730}
6731
9e0b5cb1
AG
6732/* Embedded.Processor Control */
6733
6734static void gen_msgclr(DisasContext *ctx)
6735{
6736#if defined(CONFIG_USER_ONLY)
9b2fadda 6737 GEN_PRIV;
9e0b5cb1 6738#else
9b2fadda 6739 CHK_SV;
e5f17ac6 6740 gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9b2fadda 6741#endif /* defined(CONFIG_USER_ONLY) */
9e0b5cb1
AG
6742}
6743
d5d11a39
AG
6744static void gen_msgsnd(DisasContext *ctx)
6745{
6746#if defined(CONFIG_USER_ONLY)
9b2fadda 6747 GEN_PRIV;
d5d11a39 6748#else
9b2fadda 6749 CHK_SV;
d5d11a39 6750 gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
9b2fadda 6751#endif /* defined(CONFIG_USER_ONLY) */
d5d11a39
AG
6752}
6753
a9d9eb8f
JM
6754/*** Altivec vector extension ***/
6755/* Altivec registers moves */
a9d9eb8f 6756
636aa200 6757static inline TCGv_ptr gen_avr_ptr(int reg)
564e571a 6758{
e4704b3b 6759 TCGv_ptr r = tcg_temp_new_ptr();
564e571a
AJ
6760 tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
6761 return r;
6762}
6763
a9d9eb8f 6764#define GEN_VR_LDX(name, opc2, opc3) \
99e300ef 6765static void glue(gen_, name)(DisasContext *ctx) \
a9d9eb8f 6766{ \
fe1e5c53 6767 TCGv EA; \
a9d9eb8f 6768 if (unlikely(!ctx->altivec_enabled)) { \
e06fcd75 6769 gen_exception(ctx, POWERPC_EXCP_VPU); \
a9d9eb8f
JM
6770 return; \
6771 } \
76db3ba4 6772 gen_set_access_type(ctx, ACCESS_INT); \
fe1e5c53 6773 EA = tcg_temp_new(); \
76db3ba4 6774 gen_addr_reg_index(ctx, EA); \
fe1e5c53 6775 tcg_gen_andi_tl(EA, EA, ~0xf); \
e22c357b
DK
6776 /* We only need to swap high and low halves. gen_qemu_ld64 does necessary \
6777 64-bit byteswap already. */ \
76db3ba4
AJ
6778 if (ctx->le_mode) { \
6779 gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53 6780 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6781 gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6782 } else { \
76db3ba4 6783 gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6784 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6785 gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53
AJ
6786 } \
6787 tcg_temp_free(EA); \
a9d9eb8f
JM
6788}
6789
6790#define GEN_VR_STX(name, opc2, opc3) \
99e300ef 6791static void gen_st##name(DisasContext *ctx) \
a9d9eb8f 6792{ \
fe1e5c53 6793 TCGv EA; \
a9d9eb8f 6794 if (unlikely(!ctx->altivec_enabled)) { \
e06fcd75 6795 gen_exception(ctx, POWERPC_EXCP_VPU); \
a9d9eb8f
JM
6796 return; \
6797 } \
76db3ba4 6798 gen_set_access_type(ctx, ACCESS_INT); \
fe1e5c53 6799 EA = tcg_temp_new(); \
76db3ba4 6800 gen_addr_reg_index(ctx, EA); \
fe1e5c53 6801 tcg_gen_andi_tl(EA, EA, ~0xf); \
e22c357b
DK
6802 /* We only need to swap high and low halves. gen_qemu_st64 does necessary \
6803 64-bit byteswap already. */ \
76db3ba4
AJ
6804 if (ctx->le_mode) { \
6805 gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53 6806 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6807 gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6808 } else { \
76db3ba4 6809 gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6810 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6811 gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53
AJ
6812 } \
6813 tcg_temp_free(EA); \
a9d9eb8f
JM
6814}
6815
2791128e 6816#define GEN_VR_LVE(name, opc2, opc3, size) \
99e300ef 6817static void gen_lve##name(DisasContext *ctx) \
cbfb6ae9
AJ
6818 { \
6819 TCGv EA; \
6820 TCGv_ptr rs; \
6821 if (unlikely(!ctx->altivec_enabled)) { \
6822 gen_exception(ctx, POWERPC_EXCP_VPU); \
6823 return; \
6824 } \
6825 gen_set_access_type(ctx, ACCESS_INT); \
6826 EA = tcg_temp_new(); \
6827 gen_addr_reg_index(ctx, EA); \
2791128e
TM
6828 if (size > 1) { \
6829 tcg_gen_andi_tl(EA, EA, ~(size - 1)); \
6830 } \
cbfb6ae9 6831 rs = gen_avr_ptr(rS(ctx->opcode)); \
2f5a189c 6832 gen_helper_lve##name(cpu_env, rs, EA); \
cbfb6ae9
AJ
6833 tcg_temp_free(EA); \
6834 tcg_temp_free_ptr(rs); \
6835 }
6836
2791128e 6837#define GEN_VR_STVE(name, opc2, opc3, size) \
99e300ef 6838static void gen_stve##name(DisasContext *ctx) \
cbfb6ae9
AJ
6839 { \
6840 TCGv EA; \
6841 TCGv_ptr rs; \
6842 if (unlikely(!ctx->altivec_enabled)) { \
6843 gen_exception(ctx, POWERPC_EXCP_VPU); \
6844 return; \
6845 } \
6846 gen_set_access_type(ctx, ACCESS_INT); \
6847 EA = tcg_temp_new(); \
6848 gen_addr_reg_index(ctx, EA); \
2791128e
TM
6849 if (size > 1) { \
6850 tcg_gen_andi_tl(EA, EA, ~(size - 1)); \
6851 } \
cbfb6ae9 6852 rs = gen_avr_ptr(rS(ctx->opcode)); \
2f5a189c 6853 gen_helper_stve##name(cpu_env, rs, EA); \
cbfb6ae9
AJ
6854 tcg_temp_free(EA); \
6855 tcg_temp_free_ptr(rs); \
6856 }
6857
fe1e5c53 6858GEN_VR_LDX(lvx, 0x07, 0x03);
a9d9eb8f 6859/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
fe1e5c53 6860GEN_VR_LDX(lvxl, 0x07, 0x0B);
a9d9eb8f 6861
2791128e
TM
6862GEN_VR_LVE(bx, 0x07, 0x00, 1);
6863GEN_VR_LVE(hx, 0x07, 0x01, 2);
6864GEN_VR_LVE(wx, 0x07, 0x02, 4);
cbfb6ae9 6865
fe1e5c53 6866GEN_VR_STX(svx, 0x07, 0x07);
a9d9eb8f 6867/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
fe1e5c53 6868GEN_VR_STX(svxl, 0x07, 0x0F);
a9d9eb8f 6869
2791128e
TM
6870GEN_VR_STVE(bx, 0x07, 0x04, 1);
6871GEN_VR_STVE(hx, 0x07, 0x05, 2);
6872GEN_VR_STVE(wx, 0x07, 0x06, 4);
cbfb6ae9 6873
99e300ef 6874static void gen_lvsl(DisasContext *ctx)
bf8d8ded
AJ
6875{
6876 TCGv_ptr rd;
6877 TCGv EA;
6878 if (unlikely(!ctx->altivec_enabled)) {
6879 gen_exception(ctx, POWERPC_EXCP_VPU);
6880 return;
6881 }
6882 EA = tcg_temp_new();
6883 gen_addr_reg_index(ctx, EA);
6884 rd = gen_avr_ptr(rD(ctx->opcode));
6885 gen_helper_lvsl(rd, EA);
6886 tcg_temp_free(EA);
6887 tcg_temp_free_ptr(rd);
6888}
6889
99e300ef 6890static void gen_lvsr(DisasContext *ctx)
bf8d8ded
AJ
6891{
6892 TCGv_ptr rd;
6893 TCGv EA;
6894 if (unlikely(!ctx->altivec_enabled)) {
6895 gen_exception(ctx, POWERPC_EXCP_VPU);
6896 return;
6897 }
6898 EA = tcg_temp_new();
6899 gen_addr_reg_index(ctx, EA);
6900 rd = gen_avr_ptr(rD(ctx->opcode));
6901 gen_helper_lvsr(rd, EA);
6902 tcg_temp_free(EA);
6903 tcg_temp_free_ptr(rd);
6904}
6905
99e300ef 6906static void gen_mfvscr(DisasContext *ctx)
785f451b
AJ
6907{
6908 TCGv_i32 t;
6909 if (unlikely(!ctx->altivec_enabled)) {
6910 gen_exception(ctx, POWERPC_EXCP_VPU);
6911 return;
6912 }
6913 tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
6914 t = tcg_temp_new_i32();
1328c2bf 6915 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
785f451b 6916 tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
fce5ecb7 6917 tcg_temp_free_i32(t);
785f451b
AJ
6918}
6919
99e300ef 6920static void gen_mtvscr(DisasContext *ctx)
785f451b 6921{
6e87b7c7 6922 TCGv_ptr p;
785f451b
AJ
6923 if (unlikely(!ctx->altivec_enabled)) {
6924 gen_exception(ctx, POWERPC_EXCP_VPU);
6925 return;
6926 }
76cb6584 6927 p = gen_avr_ptr(rB(ctx->opcode));
d15f74fb 6928 gen_helper_mtvscr(cpu_env, p);
6e87b7c7 6929 tcg_temp_free_ptr(p);
785f451b
AJ
6930}
6931
7a9b96cf
AJ
6932/* Logical operations */
6933#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
99e300ef 6934static void glue(gen_, name)(DisasContext *ctx) \
7a9b96cf
AJ
6935{ \
6936 if (unlikely(!ctx->altivec_enabled)) { \
6937 gen_exception(ctx, POWERPC_EXCP_VPU); \
6938 return; \
6939 } \
6940 tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
6941 tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
6942}
6943
6944GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
6945GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
6946GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
6947GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
6948GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
111c5f54
TM
6949GEN_VX_LOGICAL(veqv, tcg_gen_eqv_i64, 2, 26);
6950GEN_VX_LOGICAL(vnand, tcg_gen_nand_i64, 2, 22);
6951GEN_VX_LOGICAL(vorc, tcg_gen_orc_i64, 2, 21);
7a9b96cf 6952
8e27dd6f 6953#define GEN_VXFORM(name, opc2, opc3) \
99e300ef 6954static void glue(gen_, name)(DisasContext *ctx) \
8e27dd6f
AJ
6955{ \
6956 TCGv_ptr ra, rb, rd; \
6957 if (unlikely(!ctx->altivec_enabled)) { \
6958 gen_exception(ctx, POWERPC_EXCP_VPU); \
6959 return; \
6960 } \
6961 ra = gen_avr_ptr(rA(ctx->opcode)); \
6962 rb = gen_avr_ptr(rB(ctx->opcode)); \
6963 rd = gen_avr_ptr(rD(ctx->opcode)); \
6964 gen_helper_##name (rd, ra, rb); \
6965 tcg_temp_free_ptr(ra); \
6966 tcg_temp_free_ptr(rb); \
6967 tcg_temp_free_ptr(rd); \
6968}
6969
d15f74fb
BS
6970#define GEN_VXFORM_ENV(name, opc2, opc3) \
6971static void glue(gen_, name)(DisasContext *ctx) \
6972{ \
6973 TCGv_ptr ra, rb, rd; \
6974 if (unlikely(!ctx->altivec_enabled)) { \
6975 gen_exception(ctx, POWERPC_EXCP_VPU); \
6976 return; \
6977 } \
6978 ra = gen_avr_ptr(rA(ctx->opcode)); \
6979 rb = gen_avr_ptr(rB(ctx->opcode)); \
6980 rd = gen_avr_ptr(rD(ctx->opcode)); \
54cddd21 6981 gen_helper_##name(cpu_env, rd, ra, rb); \
d15f74fb
BS
6982 tcg_temp_free_ptr(ra); \
6983 tcg_temp_free_ptr(rb); \
6984 tcg_temp_free_ptr(rd); \
9b47bb49
TM
6985}
6986
6987#define GEN_VXFORM3(name, opc2, opc3) \
6988static void glue(gen_, name)(DisasContext *ctx) \
6989{ \
6990 TCGv_ptr ra, rb, rc, rd; \
6991 if (unlikely(!ctx->altivec_enabled)) { \
6992 gen_exception(ctx, POWERPC_EXCP_VPU); \
6993 return; \
6994 } \
6995 ra = gen_avr_ptr(rA(ctx->opcode)); \
6996 rb = gen_avr_ptr(rB(ctx->opcode)); \
6997 rc = gen_avr_ptr(rC(ctx->opcode)); \
6998 rd = gen_avr_ptr(rD(ctx->opcode)); \
6999 gen_helper_##name(rd, ra, rb, rc); \
7000 tcg_temp_free_ptr(ra); \
7001 tcg_temp_free_ptr(rb); \
7002 tcg_temp_free_ptr(rc); \
7003 tcg_temp_free_ptr(rd); \
d15f74fb
BS
7004}
7005
5dffff5a
TM
7006/*
7007 * Support for Altivec instruction pairs that use bit 31 (Rc) as
7008 * an opcode bit. In general, these pairs come from different
7009 * versions of the ISA, so we must also support a pair of flags for
7010 * each instruction.
7011 */
7012#define GEN_VXFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1) \
7013static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
7014{ \
7015 if ((Rc(ctx->opcode) == 0) && \
7016 ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
7017 gen_##name0(ctx); \
7018 } else if ((Rc(ctx->opcode) == 1) && \
7019 ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
7020 gen_##name1(ctx); \
7021 } else { \
7022 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
7023 } \
7024}
7025
7872c51c
AJ
7026GEN_VXFORM(vaddubm, 0, 0);
7027GEN_VXFORM(vadduhm, 0, 1);
7028GEN_VXFORM(vadduwm, 0, 2);
56eabc75 7029GEN_VXFORM(vaddudm, 0, 3);
7872c51c
AJ
7030GEN_VXFORM(vsububm, 0, 16);
7031GEN_VXFORM(vsubuhm, 0, 17);
7032GEN_VXFORM(vsubuwm, 0, 18);
56eabc75 7033GEN_VXFORM(vsubudm, 0, 19);
e4039339
AJ
7034GEN_VXFORM(vmaxub, 1, 0);
7035GEN_VXFORM(vmaxuh, 1, 1);
7036GEN_VXFORM(vmaxuw, 1, 2);
8203e31b 7037GEN_VXFORM(vmaxud, 1, 3);
e4039339
AJ
7038GEN_VXFORM(vmaxsb, 1, 4);
7039GEN_VXFORM(vmaxsh, 1, 5);
7040GEN_VXFORM(vmaxsw, 1, 6);
8203e31b 7041GEN_VXFORM(vmaxsd, 1, 7);
e4039339
AJ
7042GEN_VXFORM(vminub, 1, 8);
7043GEN_VXFORM(vminuh, 1, 9);
7044GEN_VXFORM(vminuw, 1, 10);
8203e31b 7045GEN_VXFORM(vminud, 1, 11);
e4039339
AJ
7046GEN_VXFORM(vminsb, 1, 12);
7047GEN_VXFORM(vminsh, 1, 13);
7048GEN_VXFORM(vminsw, 1, 14);
8203e31b 7049GEN_VXFORM(vminsd, 1, 15);
fab3cbe9
AJ
7050GEN_VXFORM(vavgub, 1, 16);
7051GEN_VXFORM(vavguh, 1, 17);
7052GEN_VXFORM(vavguw, 1, 18);
7053GEN_VXFORM(vavgsb, 1, 20);
7054GEN_VXFORM(vavgsh, 1, 21);
7055GEN_VXFORM(vavgsw, 1, 22);
3b430048
AJ
7056GEN_VXFORM(vmrghb, 6, 0);
7057GEN_VXFORM(vmrghh, 6, 1);
7058GEN_VXFORM(vmrghw, 6, 2);
7059GEN_VXFORM(vmrglb, 6, 4);
7060GEN_VXFORM(vmrglh, 6, 5);
7061GEN_VXFORM(vmrglw, 6, 6);
e0ffe77f
TM
7062
7063static void gen_vmrgew(DisasContext *ctx)
7064{
7065 TCGv_i64 tmp;
7066 int VT, VA, VB;
7067 if (unlikely(!ctx->altivec_enabled)) {
7068 gen_exception(ctx, POWERPC_EXCP_VPU);
7069 return;
7070 }
7071 VT = rD(ctx->opcode);
7072 VA = rA(ctx->opcode);
7073 VB = rB(ctx->opcode);
7074 tmp = tcg_temp_new_i64();
7075 tcg_gen_shri_i64(tmp, cpu_avrh[VB], 32);
7076 tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VA], tmp, 0, 32);
7077 tcg_gen_shri_i64(tmp, cpu_avrl[VB], 32);
7078 tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VA], tmp, 0, 32);
7079 tcg_temp_free_i64(tmp);
7080}
7081
7082static void gen_vmrgow(DisasContext *ctx)
7083{
7084 int VT, VA, VB;
7085 if (unlikely(!ctx->altivec_enabled)) {
7086 gen_exception(ctx, POWERPC_EXCP_VPU);
7087 return;
7088 }
7089 VT = rD(ctx->opcode);
7090 VA = rA(ctx->opcode);
7091 VB = rB(ctx->opcode);
7092
7093 tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VB], cpu_avrh[VA], 32, 32);
7094 tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VB], cpu_avrl[VA], 32, 32);
7095}
7096
2c277908
AJ
7097GEN_VXFORM(vmuloub, 4, 0);
7098GEN_VXFORM(vmulouh, 4, 1);
63be0936 7099GEN_VXFORM(vmulouw, 4, 2);
953f0f58
TM
7100GEN_VXFORM(vmuluwm, 4, 2);
7101GEN_VXFORM_DUAL(vmulouw, PPC_ALTIVEC, PPC_NONE,
7102 vmuluwm, PPC_NONE, PPC2_ALTIVEC_207)
2c277908
AJ
7103GEN_VXFORM(vmulosb, 4, 4);
7104GEN_VXFORM(vmulosh, 4, 5);
63be0936 7105GEN_VXFORM(vmulosw, 4, 6);
2c277908
AJ
7106GEN_VXFORM(vmuleub, 4, 8);
7107GEN_VXFORM(vmuleuh, 4, 9);
63be0936 7108GEN_VXFORM(vmuleuw, 4, 10);
2c277908
AJ
7109GEN_VXFORM(vmulesb, 4, 12);
7110GEN_VXFORM(vmulesh, 4, 13);
63be0936 7111GEN_VXFORM(vmulesw, 4, 14);
d79f0809
AJ
7112GEN_VXFORM(vslb, 2, 4);
7113GEN_VXFORM(vslh, 2, 5);
7114GEN_VXFORM(vslw, 2, 6);
2fdf78e6 7115GEN_VXFORM(vsld, 2, 23);
07ef34c3
AJ
7116GEN_VXFORM(vsrb, 2, 8);
7117GEN_VXFORM(vsrh, 2, 9);
7118GEN_VXFORM(vsrw, 2, 10);
2fdf78e6 7119GEN_VXFORM(vsrd, 2, 27);
07ef34c3
AJ
7120GEN_VXFORM(vsrab, 2, 12);
7121GEN_VXFORM(vsrah, 2, 13);
7122GEN_VXFORM(vsraw, 2, 14);
2fdf78e6 7123GEN_VXFORM(vsrad, 2, 15);
7b239bec
AJ
7124GEN_VXFORM(vslo, 6, 16);
7125GEN_VXFORM(vsro, 6, 17);
e343da72
AJ
7126GEN_VXFORM(vaddcuw, 0, 6);
7127GEN_VXFORM(vsubcuw, 0, 22);
d15f74fb
BS
7128GEN_VXFORM_ENV(vaddubs, 0, 8);
7129GEN_VXFORM_ENV(vadduhs, 0, 9);
7130GEN_VXFORM_ENV(vadduws, 0, 10);
7131GEN_VXFORM_ENV(vaddsbs, 0, 12);
7132GEN_VXFORM_ENV(vaddshs, 0, 13);
7133GEN_VXFORM_ENV(vaddsws, 0, 14);
7134GEN_VXFORM_ENV(vsububs, 0, 24);
7135GEN_VXFORM_ENV(vsubuhs, 0, 25);
7136GEN_VXFORM_ENV(vsubuws, 0, 26);
7137GEN_VXFORM_ENV(vsubsbs, 0, 28);
7138GEN_VXFORM_ENV(vsubshs, 0, 29);
7139GEN_VXFORM_ENV(vsubsws, 0, 30);
b41da4eb
TM
7140GEN_VXFORM(vadduqm, 0, 4);
7141GEN_VXFORM(vaddcuq, 0, 5);
7142GEN_VXFORM3(vaddeuqm, 30, 0);
7143GEN_VXFORM3(vaddecuq, 30, 0);
7144GEN_VXFORM_DUAL(vaddeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
7145 vaddecuq, PPC_NONE, PPC2_ALTIVEC_207)
7146GEN_VXFORM(vsubuqm, 0, 20);
7147GEN_VXFORM(vsubcuq, 0, 21);
7148GEN_VXFORM3(vsubeuqm, 31, 0);
7149GEN_VXFORM3(vsubecuq, 31, 0);
7150GEN_VXFORM_DUAL(vsubeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
7151 vsubecuq, PPC_NONE, PPC2_ALTIVEC_207)
5e1d0985
AJ
7152GEN_VXFORM(vrlb, 2, 0);
7153GEN_VXFORM(vrlh, 2, 1);
7154GEN_VXFORM(vrlw, 2, 2);
2fdf78e6 7155GEN_VXFORM(vrld, 2, 3);
d9430add
AJ
7156GEN_VXFORM(vsl, 2, 7);
7157GEN_VXFORM(vsr, 2, 11);
d15f74fb
BS
7158GEN_VXFORM_ENV(vpkuhum, 7, 0);
7159GEN_VXFORM_ENV(vpkuwum, 7, 1);
024215b2 7160GEN_VXFORM_ENV(vpkudum, 7, 17);
d15f74fb
BS
7161GEN_VXFORM_ENV(vpkuhus, 7, 2);
7162GEN_VXFORM_ENV(vpkuwus, 7, 3);
024215b2 7163GEN_VXFORM_ENV(vpkudus, 7, 19);
d15f74fb
BS
7164GEN_VXFORM_ENV(vpkshus, 7, 4);
7165GEN_VXFORM_ENV(vpkswus, 7, 5);
024215b2 7166GEN_VXFORM_ENV(vpksdus, 7, 21);
d15f74fb
BS
7167GEN_VXFORM_ENV(vpkshss, 7, 6);
7168GEN_VXFORM_ENV(vpkswss, 7, 7);
024215b2 7169GEN_VXFORM_ENV(vpksdss, 7, 23);
1dd9ffb9 7170GEN_VXFORM(vpkpx, 7, 12);
d15f74fb
BS
7171GEN_VXFORM_ENV(vsum4ubs, 4, 24);
7172GEN_VXFORM_ENV(vsum4sbs, 4, 28);
7173GEN_VXFORM_ENV(vsum4shs, 4, 25);
7174GEN_VXFORM_ENV(vsum2sws, 4, 26);
7175GEN_VXFORM_ENV(vsumsws, 4, 30);
7176GEN_VXFORM_ENV(vaddfp, 5, 0);
7177GEN_VXFORM_ENV(vsubfp, 5, 1);
7178GEN_VXFORM_ENV(vmaxfp, 5, 16);
7179GEN_VXFORM_ENV(vminfp, 5, 17);
fab3cbe9 7180
0cbcd906 7181#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
e8eaa2c0 7182static void glue(gen_, name)(DisasContext *ctx) \
0cbcd906
AJ
7183 { \
7184 TCGv_ptr ra, rb, rd; \
7185 if (unlikely(!ctx->altivec_enabled)) { \
7186 gen_exception(ctx, POWERPC_EXCP_VPU); \
7187 return; \
7188 } \
7189 ra = gen_avr_ptr(rA(ctx->opcode)); \
7190 rb = gen_avr_ptr(rB(ctx->opcode)); \
7191 rd = gen_avr_ptr(rD(ctx->opcode)); \
d15f74fb 7192 gen_helper_##opname(cpu_env, rd, ra, rb); \
0cbcd906
AJ
7193 tcg_temp_free_ptr(ra); \
7194 tcg_temp_free_ptr(rb); \
7195 tcg_temp_free_ptr(rd); \
7196 }
7197
7198#define GEN_VXRFORM(name, opc2, opc3) \
7199 GEN_VXRFORM1(name, name, #name, opc2, opc3) \
7200 GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
7201
a737d3eb
TM
7202/*
7203 * Support for Altivec instructions that use bit 31 (Rc) as an opcode
7204 * bit but also use bit 21 as an actual Rc bit. In general, thse pairs
7205 * come from different versions of the ISA, so we must also support a
7206 * pair of flags for each instruction.
7207 */
7208#define GEN_VXRFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1) \
7209static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
7210{ \
7211 if ((Rc(ctx->opcode) == 0) && \
7212 ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
7213 if (Rc21(ctx->opcode) == 0) { \
7214 gen_##name0(ctx); \
7215 } else { \
7216 gen_##name0##_(ctx); \
7217 } \
7218 } else if ((Rc(ctx->opcode) == 1) && \
7219 ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
7220 if (Rc21(ctx->opcode) == 0) { \
7221 gen_##name1(ctx); \
7222 } else { \
7223 gen_##name1##_(ctx); \
7224 } \
7225 } else { \
7226 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
7227 } \
7228}
7229
1add6e23
AJ
7230GEN_VXRFORM(vcmpequb, 3, 0)
7231GEN_VXRFORM(vcmpequh, 3, 1)
7232GEN_VXRFORM(vcmpequw, 3, 2)
6f3dab41 7233GEN_VXRFORM(vcmpequd, 3, 3)
1add6e23
AJ
7234GEN_VXRFORM(vcmpgtsb, 3, 12)
7235GEN_VXRFORM(vcmpgtsh, 3, 13)
7236GEN_VXRFORM(vcmpgtsw, 3, 14)
6f3dab41 7237GEN_VXRFORM(vcmpgtsd, 3, 15)
1add6e23
AJ
7238GEN_VXRFORM(vcmpgtub, 3, 8)
7239GEN_VXRFORM(vcmpgtuh, 3, 9)
7240GEN_VXRFORM(vcmpgtuw, 3, 10)
6f3dab41 7241GEN_VXRFORM(vcmpgtud, 3, 11)
819ca121
AJ
7242GEN_VXRFORM(vcmpeqfp, 3, 3)
7243GEN_VXRFORM(vcmpgefp, 3, 7)
7244GEN_VXRFORM(vcmpgtfp, 3, 11)
7245GEN_VXRFORM(vcmpbfp, 3, 15)
1add6e23 7246
6f3dab41
TM
7247GEN_VXRFORM_DUAL(vcmpeqfp, PPC_ALTIVEC, PPC_NONE, \
7248 vcmpequd, PPC_NONE, PPC2_ALTIVEC_207)
7249GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
7250 vcmpgtsd, PPC_NONE, PPC2_ALTIVEC_207)
7251GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \
7252 vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207)
7253
c026766b 7254#define GEN_VXFORM_SIMM(name, opc2, opc3) \
99e300ef 7255static void glue(gen_, name)(DisasContext *ctx) \
c026766b
AJ
7256 { \
7257 TCGv_ptr rd; \
7258 TCGv_i32 simm; \
7259 if (unlikely(!ctx->altivec_enabled)) { \
7260 gen_exception(ctx, POWERPC_EXCP_VPU); \
7261 return; \
7262 } \
7263 simm = tcg_const_i32(SIMM5(ctx->opcode)); \
7264 rd = gen_avr_ptr(rD(ctx->opcode)); \
7265 gen_helper_##name (rd, simm); \
7266 tcg_temp_free_i32(simm); \
7267 tcg_temp_free_ptr(rd); \
7268 }
7269
7270GEN_VXFORM_SIMM(vspltisb, 6, 12);
7271GEN_VXFORM_SIMM(vspltish, 6, 13);
7272GEN_VXFORM_SIMM(vspltisw, 6, 14);
7273
de5f2484 7274#define GEN_VXFORM_NOA(name, opc2, opc3) \
99e300ef 7275static void glue(gen_, name)(DisasContext *ctx) \
de5f2484
AJ
7276 { \
7277 TCGv_ptr rb, rd; \
7278 if (unlikely(!ctx->altivec_enabled)) { \
7279 gen_exception(ctx, POWERPC_EXCP_VPU); \
7280 return; \
7281 } \
7282 rb = gen_avr_ptr(rB(ctx->opcode)); \
7283 rd = gen_avr_ptr(rD(ctx->opcode)); \
7284 gen_helper_##name (rd, rb); \
7285 tcg_temp_free_ptr(rb); \
7286 tcg_temp_free_ptr(rd); \
7287 }
7288
d15f74fb
BS
7289#define GEN_VXFORM_NOA_ENV(name, opc2, opc3) \
7290static void glue(gen_, name)(DisasContext *ctx) \
7291 { \
7292 TCGv_ptr rb, rd; \
7293 \
7294 if (unlikely(!ctx->altivec_enabled)) { \
7295 gen_exception(ctx, POWERPC_EXCP_VPU); \
7296 return; \
7297 } \
7298 rb = gen_avr_ptr(rB(ctx->opcode)); \
7299 rd = gen_avr_ptr(rD(ctx->opcode)); \
7300 gen_helper_##name(cpu_env, rd, rb); \
7301 tcg_temp_free_ptr(rb); \
7302 tcg_temp_free_ptr(rd); \
7303 }
7304
6cf1c6e5
AJ
7305GEN_VXFORM_NOA(vupkhsb, 7, 8);
7306GEN_VXFORM_NOA(vupkhsh, 7, 9);
4430e076 7307GEN_VXFORM_NOA(vupkhsw, 7, 25);
6cf1c6e5
AJ
7308GEN_VXFORM_NOA(vupklsb, 7, 10);
7309GEN_VXFORM_NOA(vupklsh, 7, 11);
4430e076 7310GEN_VXFORM_NOA(vupklsw, 7, 27);
79f85c3a
AJ
7311GEN_VXFORM_NOA(vupkhpx, 7, 13);
7312GEN_VXFORM_NOA(vupklpx, 7, 15);
d15f74fb
BS
7313GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
7314GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
7315GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
7316GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
abe60a43
TM
7317GEN_VXFORM_NOA_ENV(vrfim, 5, 11);
7318GEN_VXFORM_NOA_ENV(vrfin, 5, 8);
d15f74fb 7319GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
abe60a43 7320GEN_VXFORM_NOA_ENV(vrfiz, 5, 9);
79f85c3a 7321
21d21583 7322#define GEN_VXFORM_SIMM(name, opc2, opc3) \
99e300ef 7323static void glue(gen_, name)(DisasContext *ctx) \
21d21583
AJ
7324 { \
7325 TCGv_ptr rd; \
7326 TCGv_i32 simm; \
7327 if (unlikely(!ctx->altivec_enabled)) { \
7328 gen_exception(ctx, POWERPC_EXCP_VPU); \
7329 return; \
7330 } \
7331 simm = tcg_const_i32(SIMM5(ctx->opcode)); \
7332 rd = gen_avr_ptr(rD(ctx->opcode)); \
7333 gen_helper_##name (rd, simm); \
7334 tcg_temp_free_i32(simm); \
7335 tcg_temp_free_ptr(rd); \
7336 }
7337
27a4edb3 7338#define GEN_VXFORM_UIMM(name, opc2, opc3) \
99e300ef 7339static void glue(gen_, name)(DisasContext *ctx) \
27a4edb3
AJ
7340 { \
7341 TCGv_ptr rb, rd; \
7342 TCGv_i32 uimm; \
7343 if (unlikely(!ctx->altivec_enabled)) { \
7344 gen_exception(ctx, POWERPC_EXCP_VPU); \
7345 return; \
7346 } \
7347 uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
7348 rb = gen_avr_ptr(rB(ctx->opcode)); \
7349 rd = gen_avr_ptr(rD(ctx->opcode)); \
7350 gen_helper_##name (rd, rb, uimm); \
7351 tcg_temp_free_i32(uimm); \
7352 tcg_temp_free_ptr(rb); \
7353 tcg_temp_free_ptr(rd); \
7354 }
7355
d15f74fb
BS
7356#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3) \
7357static void glue(gen_, name)(DisasContext *ctx) \
7358 { \
7359 TCGv_ptr rb, rd; \
7360 TCGv_i32 uimm; \
7361 \
7362 if (unlikely(!ctx->altivec_enabled)) { \
7363 gen_exception(ctx, POWERPC_EXCP_VPU); \
7364 return; \
7365 } \
7366 uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
7367 rb = gen_avr_ptr(rB(ctx->opcode)); \
7368 rd = gen_avr_ptr(rD(ctx->opcode)); \
7369 gen_helper_##name(cpu_env, rd, rb, uimm); \
7370 tcg_temp_free_i32(uimm); \
7371 tcg_temp_free_ptr(rb); \
7372 tcg_temp_free_ptr(rd); \
7373 }
7374
e4e6bee7
AJ
7375GEN_VXFORM_UIMM(vspltb, 6, 8);
7376GEN_VXFORM_UIMM(vsplth, 6, 9);
7377GEN_VXFORM_UIMM(vspltw, 6, 10);
d15f74fb
BS
7378GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
7379GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
7380GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
7381GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
e4e6bee7 7382
99e300ef 7383static void gen_vsldoi(DisasContext *ctx)
cd633b10
AJ
7384{
7385 TCGv_ptr ra, rb, rd;
fce5ecb7 7386 TCGv_i32 sh;
cd633b10
AJ
7387 if (unlikely(!ctx->altivec_enabled)) {
7388 gen_exception(ctx, POWERPC_EXCP_VPU);
7389 return;
7390 }
7391 ra = gen_avr_ptr(rA(ctx->opcode));
7392 rb = gen_avr_ptr(rB(ctx->opcode));
7393 rd = gen_avr_ptr(rD(ctx->opcode));
7394 sh = tcg_const_i32(VSH(ctx->opcode));
7395 gen_helper_vsldoi (rd, ra, rb, sh);
7396 tcg_temp_free_ptr(ra);
7397 tcg_temp_free_ptr(rb);
7398 tcg_temp_free_ptr(rd);
fce5ecb7 7399 tcg_temp_free_i32(sh);
cd633b10
AJ
7400}
7401
707cec33 7402#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
d15f74fb 7403static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
707cec33
AJ
7404 { \
7405 TCGv_ptr ra, rb, rc, rd; \
7406 if (unlikely(!ctx->altivec_enabled)) { \
7407 gen_exception(ctx, POWERPC_EXCP_VPU); \
7408 return; \
7409 } \
7410 ra = gen_avr_ptr(rA(ctx->opcode)); \
7411 rb = gen_avr_ptr(rB(ctx->opcode)); \
7412 rc = gen_avr_ptr(rC(ctx->opcode)); \
7413 rd = gen_avr_ptr(rD(ctx->opcode)); \
7414 if (Rc(ctx->opcode)) { \
d15f74fb 7415 gen_helper_##name1(cpu_env, rd, ra, rb, rc); \
707cec33 7416 } else { \
d15f74fb 7417 gen_helper_##name0(cpu_env, rd, ra, rb, rc); \
707cec33
AJ
7418 } \
7419 tcg_temp_free_ptr(ra); \
7420 tcg_temp_free_ptr(rb); \
7421 tcg_temp_free_ptr(rc); \
7422 tcg_temp_free_ptr(rd); \
7423 }
7424
b161ae27
AJ
7425GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
7426
99e300ef 7427static void gen_vmladduhm(DisasContext *ctx)
bcd2ee23
AJ
7428{
7429 TCGv_ptr ra, rb, rc, rd;
7430 if (unlikely(!ctx->altivec_enabled)) {
7431 gen_exception(ctx, POWERPC_EXCP_VPU);
7432 return;
7433 }
7434 ra = gen_avr_ptr(rA(ctx->opcode));
7435 rb = gen_avr_ptr(rB(ctx->opcode));
7436 rc = gen_avr_ptr(rC(ctx->opcode));
7437 rd = gen_avr_ptr(rD(ctx->opcode));
7438 gen_helper_vmladduhm(rd, ra, rb, rc);
7439 tcg_temp_free_ptr(ra);
7440 tcg_temp_free_ptr(rb);
7441 tcg_temp_free_ptr(rc);
7442 tcg_temp_free_ptr(rd);
7443}
7444
b04ae981 7445GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
4d9903b6 7446GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
eae07261 7447GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
d1258698 7448GEN_VAFORM_PAIRED(vsel, vperm, 21)
35cf7c7e 7449GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
b04ae981 7450
f293f04a
TM
7451GEN_VXFORM_NOA(vclzb, 1, 28)
7452GEN_VXFORM_NOA(vclzh, 1, 29)
7453GEN_VXFORM_NOA(vclzw, 1, 30)
7454GEN_VXFORM_NOA(vclzd, 1, 31)
e13500b3
TM
7455GEN_VXFORM_NOA(vpopcntb, 1, 28)
7456GEN_VXFORM_NOA(vpopcnth, 1, 29)
7457GEN_VXFORM_NOA(vpopcntw, 1, 30)
7458GEN_VXFORM_NOA(vpopcntd, 1, 31)
7459GEN_VXFORM_DUAL(vclzb, PPC_NONE, PPC2_ALTIVEC_207, \
7460 vpopcntb, PPC_NONE, PPC2_ALTIVEC_207)
7461GEN_VXFORM_DUAL(vclzh, PPC_NONE, PPC2_ALTIVEC_207, \
7462 vpopcnth, PPC_NONE, PPC2_ALTIVEC_207)
7463GEN_VXFORM_DUAL(vclzw, PPC_NONE, PPC2_ALTIVEC_207, \
7464 vpopcntw, PPC_NONE, PPC2_ALTIVEC_207)
7465GEN_VXFORM_DUAL(vclzd, PPC_NONE, PPC2_ALTIVEC_207, \
7466 vpopcntd, PPC_NONE, PPC2_ALTIVEC_207)
4d82038e 7467GEN_VXFORM(vbpermq, 6, 21);
f1064f61 7468GEN_VXFORM_NOA(vgbbd, 6, 20);
b8476fc7
TM
7469GEN_VXFORM(vpmsumb, 4, 16)
7470GEN_VXFORM(vpmsumh, 4, 17)
7471GEN_VXFORM(vpmsumw, 4, 18)
7472GEN_VXFORM(vpmsumd, 4, 19)
e13500b3 7473
e8f7b27b
TM
7474#define GEN_BCD(op) \
7475static void gen_##op(DisasContext *ctx) \
7476{ \
7477 TCGv_ptr ra, rb, rd; \
7478 TCGv_i32 ps; \
7479 \
7480 if (unlikely(!ctx->altivec_enabled)) { \
7481 gen_exception(ctx, POWERPC_EXCP_VPU); \
7482 return; \
7483 } \
7484 \
7485 ra = gen_avr_ptr(rA(ctx->opcode)); \
7486 rb = gen_avr_ptr(rB(ctx->opcode)); \
7487 rd = gen_avr_ptr(rD(ctx->opcode)); \
7488 \
7489 ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
7490 \
7491 gen_helper_##op(cpu_crf[6], rd, ra, rb, ps); \
7492 \
7493 tcg_temp_free_ptr(ra); \
7494 tcg_temp_free_ptr(rb); \
7495 tcg_temp_free_ptr(rd); \
7496 tcg_temp_free_i32(ps); \
7497}
7498
7499GEN_BCD(bcdadd)
7500GEN_BCD(bcdsub)
7501
7502GEN_VXFORM_DUAL(vsububm, PPC_ALTIVEC, PPC_NONE, \
7503 bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
7504GEN_VXFORM_DUAL(vsububs, PPC_ALTIVEC, PPC_NONE, \
7505 bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
7506GEN_VXFORM_DUAL(vsubuhm, PPC_ALTIVEC, PPC_NONE, \
7507 bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
7508GEN_VXFORM_DUAL(vsubuhs, PPC_ALTIVEC, PPC_NONE, \
7509 bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
7510
557d52fa
TM
7511static void gen_vsbox(DisasContext *ctx)
7512{
7513 TCGv_ptr ra, rd;
7514 if (unlikely(!ctx->altivec_enabled)) {
7515 gen_exception(ctx, POWERPC_EXCP_VPU);
7516 return;
7517 }
7518 ra = gen_avr_ptr(rA(ctx->opcode));
7519 rd = gen_avr_ptr(rD(ctx->opcode));
7520 gen_helper_vsbox(rd, ra);
7521 tcg_temp_free_ptr(ra);
7522 tcg_temp_free_ptr(rd);
7523}
7524
7525GEN_VXFORM(vcipher, 4, 20)
7526GEN_VXFORM(vcipherlast, 4, 20)
7527GEN_VXFORM(vncipher, 4, 21)
7528GEN_VXFORM(vncipherlast, 4, 21)
7529
7530GEN_VXFORM_DUAL(vcipher, PPC_NONE, PPC2_ALTIVEC_207,
7531 vcipherlast, PPC_NONE, PPC2_ALTIVEC_207)
7532GEN_VXFORM_DUAL(vncipher, PPC_NONE, PPC2_ALTIVEC_207,
7533 vncipherlast, PPC_NONE, PPC2_ALTIVEC_207)
7534
57354f8f
TM
7535#define VSHASIGMA(op) \
7536static void gen_##op(DisasContext *ctx) \
7537{ \
7538 TCGv_ptr ra, rd; \
7539 TCGv_i32 st_six; \
7540 if (unlikely(!ctx->altivec_enabled)) { \
7541 gen_exception(ctx, POWERPC_EXCP_VPU); \
7542 return; \
7543 } \
7544 ra = gen_avr_ptr(rA(ctx->opcode)); \
7545 rd = gen_avr_ptr(rD(ctx->opcode)); \
7546 st_six = tcg_const_i32(rB(ctx->opcode)); \
7547 gen_helper_##op(rd, ra, st_six); \
7548 tcg_temp_free_ptr(ra); \
7549 tcg_temp_free_ptr(rd); \
7550 tcg_temp_free_i32(st_six); \
7551}
7552
7553VSHASIGMA(vshasigmaw)
7554VSHASIGMA(vshasigmad)
7555
ac174549
TM
7556GEN_VXFORM3(vpermxor, 22, 0xFF)
7557GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
7558 vpermxor, PPC_NONE, PPC2_ALTIVEC_207)
7559
472b24ce
TM
7560/*** VSX extension ***/
7561
7562static inline TCGv_i64 cpu_vsrh(int n)
7563{
7564 if (n < 32) {
7565 return cpu_fpr[n];
7566 } else {
7567 return cpu_avrh[n-32];
7568 }
7569}
7570
7571static inline TCGv_i64 cpu_vsrl(int n)
7572{
7573 if (n < 32) {
7574 return cpu_vsr[n];
7575 } else {
7576 return cpu_avrl[n-32];
7577 }
7578}
7579
e072fe79
TM
7580#define VSX_LOAD_SCALAR(name, operation) \
7581static void gen_##name(DisasContext *ctx) \
7582{ \
7583 TCGv EA; \
7584 if (unlikely(!ctx->vsx_enabled)) { \
7585 gen_exception(ctx, POWERPC_EXCP_VSXU); \
7586 return; \
7587 } \
7588 gen_set_access_type(ctx, ACCESS_INT); \
7589 EA = tcg_temp_new(); \
7590 gen_addr_reg_index(ctx, EA); \
7591 gen_qemu_##operation(ctx, cpu_vsrh(xT(ctx->opcode)), EA); \
7592 /* NOTE: cpu_vsrl is undefined */ \
7593 tcg_temp_free(EA); \
7594}
7595
7596VSX_LOAD_SCALAR(lxsdx, ld64)
cac7f0ba
TM
7597VSX_LOAD_SCALAR(lxsiwax, ld32s_i64)
7598VSX_LOAD_SCALAR(lxsiwzx, ld32u_i64)
7599VSX_LOAD_SCALAR(lxsspx, ld32fs)
fa1832d7 7600
304af367
TM
7601static void gen_lxvd2x(DisasContext *ctx)
7602{
7603 TCGv EA;
7604 if (unlikely(!ctx->vsx_enabled)) {
7605 gen_exception(ctx, POWERPC_EXCP_VSXU);
7606 return;
7607 }
7608 gen_set_access_type(ctx, ACCESS_INT);
7609 EA = tcg_temp_new();
7610 gen_addr_reg_index(ctx, EA);
7611 gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
7612 tcg_gen_addi_tl(EA, EA, 8);
7613 gen_qemu_ld64(ctx, cpu_vsrl(xT(ctx->opcode)), EA);
7614 tcg_temp_free(EA);
7615}
7616
ca03b467
TM
7617static void gen_lxvdsx(DisasContext *ctx)
7618{
7619 TCGv EA;
7620 if (unlikely(!ctx->vsx_enabled)) {
7621 gen_exception(ctx, POWERPC_EXCP_VSXU);
7622 return;
7623 }
7624 gen_set_access_type(ctx, ACCESS_INT);
7625 EA = tcg_temp_new();
7626 gen_addr_reg_index(ctx, EA);
7627 gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
f976b09e 7628 tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
ca03b467
TM
7629 tcg_temp_free(EA);
7630}
7631
897e61d1
TM
7632static void gen_lxvw4x(DisasContext *ctx)
7633{
f976b09e
AG
7634 TCGv EA;
7635 TCGv_i64 tmp;
897e61d1
TM
7636 TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
7637 TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
7638 if (unlikely(!ctx->vsx_enabled)) {
7639 gen_exception(ctx, POWERPC_EXCP_VSXU);
7640 return;
7641 }
7642 gen_set_access_type(ctx, ACCESS_INT);
7643 EA = tcg_temp_new();
f976b09e
AG
7644 tmp = tcg_temp_new_i64();
7645
897e61d1 7646 gen_addr_reg_index(ctx, EA);
f976b09e 7647 gen_qemu_ld32u_i64(ctx, tmp, EA);
897e61d1 7648 tcg_gen_addi_tl(EA, EA, 4);
f976b09e 7649 gen_qemu_ld32u_i64(ctx, xth, EA);
897e61d1
TM
7650 tcg_gen_deposit_i64(xth, xth, tmp, 32, 32);
7651
7652 tcg_gen_addi_tl(EA, EA, 4);
f976b09e 7653 gen_qemu_ld32u_i64(ctx, tmp, EA);
897e61d1 7654 tcg_gen_addi_tl(EA, EA, 4);
f976b09e 7655 gen_qemu_ld32u_i64(ctx, xtl, EA);
897e61d1
TM
7656 tcg_gen_deposit_i64(xtl, xtl, tmp, 32, 32);
7657
7658 tcg_temp_free(EA);
f976b09e 7659 tcg_temp_free_i64(tmp);
897e61d1
TM
7660}
7661
f026da78
TM
7662#define VSX_STORE_SCALAR(name, operation) \
7663static void gen_##name(DisasContext *ctx) \
7664{ \
7665 TCGv EA; \
7666 if (unlikely(!ctx->vsx_enabled)) { \
7667 gen_exception(ctx, POWERPC_EXCP_VSXU); \
7668 return; \
7669 } \
7670 gen_set_access_type(ctx, ACCESS_INT); \
7671 EA = tcg_temp_new(); \
7672 gen_addr_reg_index(ctx, EA); \
7673 gen_qemu_##operation(ctx, cpu_vsrh(xS(ctx->opcode)), EA); \
7674 tcg_temp_free(EA); \
9231ba9e
TM
7675}
7676
f026da78 7677VSX_STORE_SCALAR(stxsdx, st64)
e16a626b
TM
7678VSX_STORE_SCALAR(stxsiwx, st32_i64)
7679VSX_STORE_SCALAR(stxsspx, st32fs)
f026da78 7680
fbed2478
TM
7681static void gen_stxvd2x(DisasContext *ctx)
7682{
7683 TCGv EA;
7684 if (unlikely(!ctx->vsx_enabled)) {
7685 gen_exception(ctx, POWERPC_EXCP_VSXU);
7686 return;
7687 }
7688 gen_set_access_type(ctx, ACCESS_INT);
7689 EA = tcg_temp_new();
7690 gen_addr_reg_index(ctx, EA);
7691 gen_qemu_st64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
7692 tcg_gen_addi_tl(EA, EA, 8);
7693 gen_qemu_st64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
7694 tcg_temp_free(EA);
7695}
7696
86e61ce3
TM
7697static void gen_stxvw4x(DisasContext *ctx)
7698{
f976b09e
AG
7699 TCGv_i64 tmp;
7700 TCGv EA;
86e61ce3
TM
7701 if (unlikely(!ctx->vsx_enabled)) {
7702 gen_exception(ctx, POWERPC_EXCP_VSXU);
7703 return;
7704 }
7705 gen_set_access_type(ctx, ACCESS_INT);
7706 EA = tcg_temp_new();
7707 gen_addr_reg_index(ctx, EA);
f976b09e 7708 tmp = tcg_temp_new_i64();
86e61ce3
TM
7709
7710 tcg_gen_shri_i64(tmp, cpu_vsrh(xS(ctx->opcode)), 32);
f976b09e 7711 gen_qemu_st32_i64(ctx, tmp, EA);
86e61ce3 7712 tcg_gen_addi_tl(EA, EA, 4);
f976b09e 7713 gen_qemu_st32_i64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
86e61ce3
TM
7714
7715 tcg_gen_shri_i64(tmp, cpu_vsrl(xS(ctx->opcode)), 32);
7716 tcg_gen_addi_tl(EA, EA, 4);
f976b09e 7717 gen_qemu_st32_i64(ctx, tmp, EA);
86e61ce3 7718 tcg_gen_addi_tl(EA, EA, 4);
f976b09e 7719 gen_qemu_st32_i64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
86e61ce3
TM
7720
7721 tcg_temp_free(EA);
f976b09e 7722 tcg_temp_free_i64(tmp);
86e61ce3
TM
7723}
7724
f5c0f7f9
TM
7725#define MV_VSRW(name, tcgop1, tcgop2, target, source) \
7726static void gen_##name(DisasContext *ctx) \
7727{ \
7728 if (xS(ctx->opcode) < 32) { \
7729 if (unlikely(!ctx->fpu_enabled)) { \
7730 gen_exception(ctx, POWERPC_EXCP_FPU); \
7731 return; \
7732 } \
7733 } else { \
7734 if (unlikely(!ctx->altivec_enabled)) { \
7735 gen_exception(ctx, POWERPC_EXCP_VPU); \
7736 return; \
7737 } \
7738 } \
7739 TCGv_i64 tmp = tcg_temp_new_i64(); \
7740 tcg_gen_##tcgop1(tmp, source); \
7741 tcg_gen_##tcgop2(target, tmp); \
7742 tcg_temp_free_i64(tmp); \
7743}
7744
7745
7746MV_VSRW(mfvsrwz, ext32u_i64, trunc_i64_tl, cpu_gpr[rA(ctx->opcode)], \
7747 cpu_vsrh(xS(ctx->opcode)))
7748MV_VSRW(mtvsrwa, extu_tl_i64, ext32s_i64, cpu_vsrh(xT(ctx->opcode)), \
7749 cpu_gpr[rA(ctx->opcode)])
7750MV_VSRW(mtvsrwz, extu_tl_i64, ext32u_i64, cpu_vsrh(xT(ctx->opcode)), \
7751 cpu_gpr[rA(ctx->opcode)])
7752
7753#if defined(TARGET_PPC64)
7754#define MV_VSRD(name, target, source) \
7755static void gen_##name(DisasContext *ctx) \
7756{ \
7757 if (xS(ctx->opcode) < 32) { \
7758 if (unlikely(!ctx->fpu_enabled)) { \
7759 gen_exception(ctx, POWERPC_EXCP_FPU); \
7760 return; \
7761 } \
7762 } else { \
7763 if (unlikely(!ctx->altivec_enabled)) { \
7764 gen_exception(ctx, POWERPC_EXCP_VPU); \
7765 return; \
7766 } \
7767 } \
7768 tcg_gen_mov_i64(target, source); \
7769}
7770
7771MV_VSRD(mfvsrd, cpu_gpr[rA(ctx->opcode)], cpu_vsrh(xS(ctx->opcode)))
7772MV_VSRD(mtvsrd, cpu_vsrh(xT(ctx->opcode)), cpu_gpr[rA(ctx->opcode)])
7773
7774#endif
7775
cd73f2c9
TM
7776static void gen_xxpermdi(DisasContext *ctx)
7777{
7778 if (unlikely(!ctx->vsx_enabled)) {
7779 gen_exception(ctx, POWERPC_EXCP_VSXU);
7780 return;
7781 }
7782
f5bc1bfa
TM
7783 if (unlikely((xT(ctx->opcode) == xA(ctx->opcode)) ||
7784 (xT(ctx->opcode) == xB(ctx->opcode)))) {
7785 TCGv_i64 xh, xl;
7786
7787 xh = tcg_temp_new_i64();
7788 xl = tcg_temp_new_i64();
7789
7790 if ((DM(ctx->opcode) & 2) == 0) {
7791 tcg_gen_mov_i64(xh, cpu_vsrh(xA(ctx->opcode)));
7792 } else {
7793 tcg_gen_mov_i64(xh, cpu_vsrl(xA(ctx->opcode)));
7794 }
7795 if ((DM(ctx->opcode) & 1) == 0) {
7796 tcg_gen_mov_i64(xl, cpu_vsrh(xB(ctx->opcode)));
7797 } else {
7798 tcg_gen_mov_i64(xl, cpu_vsrl(xB(ctx->opcode)));
7799 }
7800
7801 tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xh);
7802 tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xl);
7803
7804 tcg_temp_free_i64(xh);
7805 tcg_temp_free_i64(xl);
cd73f2c9 7806 } else {
f5bc1bfa
TM
7807 if ((DM(ctx->opcode) & 2) == 0) {
7808 tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)));
7809 } else {
7810 tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)));
7811 }
7812 if ((DM(ctx->opcode) & 1) == 0) {
7813 tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xB(ctx->opcode)));
7814 } else {
7815 tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xB(ctx->opcode)));
7816 }
cd73f2c9
TM
7817 }
7818}
7819
df020ce0
TM
7820#define OP_ABS 1
7821#define OP_NABS 2
7822#define OP_NEG 3
7823#define OP_CPSGN 4
e5d7d2b0
PM
7824#define SGN_MASK_DP 0x8000000000000000ull
7825#define SGN_MASK_SP 0x8000000080000000ull
df020ce0
TM
7826
7827#define VSX_SCALAR_MOVE(name, op, sgn_mask) \
7828static void glue(gen_, name)(DisasContext * ctx) \
7829 { \
7830 TCGv_i64 xb, sgm; \
7831 if (unlikely(!ctx->vsx_enabled)) { \
7832 gen_exception(ctx, POWERPC_EXCP_VSXU); \
7833 return; \
7834 } \
f976b09e
AG
7835 xb = tcg_temp_new_i64(); \
7836 sgm = tcg_temp_new_i64(); \
df020ce0
TM
7837 tcg_gen_mov_i64(xb, cpu_vsrh(xB(ctx->opcode))); \
7838 tcg_gen_movi_i64(sgm, sgn_mask); \
7839 switch (op) { \
7840 case OP_ABS: { \
7841 tcg_gen_andc_i64(xb, xb, sgm); \
7842 break; \
7843 } \
7844 case OP_NABS: { \
7845 tcg_gen_or_i64(xb, xb, sgm); \
7846 break; \
7847 } \
7848 case OP_NEG: { \
7849 tcg_gen_xor_i64(xb, xb, sgm); \
7850 break; \
7851 } \
7852 case OP_CPSGN: { \
f976b09e 7853 TCGv_i64 xa = tcg_temp_new_i64(); \
df020ce0
TM
7854 tcg_gen_mov_i64(xa, cpu_vsrh(xA(ctx->opcode))); \
7855 tcg_gen_and_i64(xa, xa, sgm); \
7856 tcg_gen_andc_i64(xb, xb, sgm); \
7857 tcg_gen_or_i64(xb, xb, xa); \
f976b09e 7858 tcg_temp_free_i64(xa); \
df020ce0
TM
7859 break; \
7860 } \
7861 } \
7862 tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xb); \
f976b09e
AG
7863 tcg_temp_free_i64(xb); \
7864 tcg_temp_free_i64(sgm); \
df020ce0
TM
7865 }
7866
7867VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP)
7868VSX_SCALAR_MOVE(xsnabsdp, OP_NABS, SGN_MASK_DP)
7869VSX_SCALAR_MOVE(xsnegdp, OP_NEG, SGN_MASK_DP)
7870VSX_SCALAR_MOVE(xscpsgndp, OP_CPSGN, SGN_MASK_DP)
7871
be574920
TM
7872#define VSX_VECTOR_MOVE(name, op, sgn_mask) \
7873static void glue(gen_, name)(DisasContext * ctx) \
7874 { \
7875 TCGv_i64 xbh, xbl, sgm; \
7876 if (unlikely(!ctx->vsx_enabled)) { \
7877 gen_exception(ctx, POWERPC_EXCP_VSXU); \
7878 return; \
7879 } \
f976b09e
AG
7880 xbh = tcg_temp_new_i64(); \
7881 xbl = tcg_temp_new_i64(); \
7882 sgm = tcg_temp_new_i64(); \
be574920
TM
7883 tcg_gen_mov_i64(xbh, cpu_vsrh(xB(ctx->opcode))); \
7884 tcg_gen_mov_i64(xbl, cpu_vsrl(xB(ctx->opcode))); \
7885 tcg_gen_movi_i64(sgm, sgn_mask); \
7886 switch (op) { \
7887 case OP_ABS: { \
7888 tcg_gen_andc_i64(xbh, xbh, sgm); \
7889 tcg_gen_andc_i64(xbl, xbl, sgm); \
7890 break; \
7891 } \
7892 case OP_NABS: { \
7893 tcg_gen_or_i64(xbh, xbh, sgm); \
7894 tcg_gen_or_i64(xbl, xbl, sgm); \
7895 break; \
7896 } \
7897 case OP_NEG: { \
7898 tcg_gen_xor_i64(xbh, xbh, sgm); \
7899 tcg_gen_xor_i64(xbl, xbl, sgm); \
7900 break; \
7901 } \
7902 case OP_CPSGN: { \
f976b09e
AG
7903 TCGv_i64 xah = tcg_temp_new_i64(); \
7904 TCGv_i64 xal = tcg_temp_new_i64(); \
be574920
TM
7905 tcg_gen_mov_i64(xah, cpu_vsrh(xA(ctx->opcode))); \
7906 tcg_gen_mov_i64(xal, cpu_vsrl(xA(ctx->opcode))); \
7907 tcg_gen_and_i64(xah, xah, sgm); \
7908 tcg_gen_and_i64(xal, xal, sgm); \
7909 tcg_gen_andc_i64(xbh, xbh, sgm); \
7910 tcg_gen_andc_i64(xbl, xbl, sgm); \
7911 tcg_gen_or_i64(xbh, xbh, xah); \
7912 tcg_gen_or_i64(xbl, xbl, xal); \
f976b09e
AG
7913 tcg_temp_free_i64(xah); \
7914 tcg_temp_free_i64(xal); \
be574920
TM
7915 break; \
7916 } \
7917 } \
7918 tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xbh); \
7919 tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xbl); \
f976b09e
AG
7920 tcg_temp_free_i64(xbh); \
7921 tcg_temp_free_i64(xbl); \
7922 tcg_temp_free_i64(sgm); \
be574920
TM
7923 }
7924
7925VSX_VECTOR_MOVE(xvabsdp, OP_ABS, SGN_MASK_DP)
7926VSX_VECTOR_MOVE(xvnabsdp, OP_NABS, SGN_MASK_DP)
7927VSX_VECTOR_MOVE(xvnegdp, OP_NEG, SGN_MASK_DP)
7928VSX_VECTOR_MOVE(xvcpsgndp, OP_CPSGN, SGN_MASK_DP)
7929VSX_VECTOR_MOVE(xvabssp, OP_ABS, SGN_MASK_SP)
7930VSX_VECTOR_MOVE(xvnabssp, OP_NABS, SGN_MASK_SP)
7931VSX_VECTOR_MOVE(xvnegsp, OP_NEG, SGN_MASK_SP)
7932VSX_VECTOR_MOVE(xvcpsgnsp, OP_CPSGN, SGN_MASK_SP)
7933
3c3cbbdc
TM
7934#define GEN_VSX_HELPER_2(name, op1, op2, inval, type) \
7935static void gen_##name(DisasContext * ctx) \
7936{ \
7937 TCGv_i32 opc; \
7938 if (unlikely(!ctx->vsx_enabled)) { \
7939 gen_exception(ctx, POWERPC_EXCP_VSXU); \
7940 return; \
7941 } \
7942 /* NIP cannot be restored if the memory exception comes from an helper */ \
7943 gen_update_nip(ctx, ctx->nip - 4); \
7944 opc = tcg_const_i32(ctx->opcode); \
7945 gen_helper_##name(cpu_env, opc); \
7946 tcg_temp_free_i32(opc); \
7947}
be574920 7948
3d1140bf
TM
7949#define GEN_VSX_HELPER_XT_XB_ENV(name, op1, op2, inval, type) \
7950static void gen_##name(DisasContext * ctx) \
7951{ \
7952 if (unlikely(!ctx->vsx_enabled)) { \
7953 gen_exception(ctx, POWERPC_EXCP_VSXU); \
7954 return; \
7955 } \
7956 /* NIP cannot be restored if the exception comes */ \
7957 /* from a helper. */ \
7958 gen_update_nip(ctx, ctx->nip - 4); \
7959 \
7960 gen_helper_##name(cpu_vsrh(xT(ctx->opcode)), cpu_env, \
7961 cpu_vsrh(xB(ctx->opcode))); \
7962}
7963
ee6e02c0
TM
7964GEN_VSX_HELPER_2(xsadddp, 0x00, 0x04, 0, PPC2_VSX)
7965GEN_VSX_HELPER_2(xssubdp, 0x00, 0x05, 0, PPC2_VSX)
5e591d88 7966GEN_VSX_HELPER_2(xsmuldp, 0x00, 0x06, 0, PPC2_VSX)
4b98eeef 7967GEN_VSX_HELPER_2(xsdivdp, 0x00, 0x07, 0, PPC2_VSX)
2009227f 7968GEN_VSX_HELPER_2(xsredp, 0x14, 0x05, 0, PPC2_VSX)
d32404fe 7969GEN_VSX_HELPER_2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX)
d3f9df8f 7970GEN_VSX_HELPER_2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX)
bc80838f 7971GEN_VSX_HELPER_2(xstdivdp, 0x14, 0x07, 0, PPC2_VSX)
5cb151ac 7972GEN_VSX_HELPER_2(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX)
595c6eef
TM
7973GEN_VSX_HELPER_2(xsmaddadp, 0x04, 0x04, 0, PPC2_VSX)
7974GEN_VSX_HELPER_2(xsmaddmdp, 0x04, 0x05, 0, PPC2_VSX)
7975GEN_VSX_HELPER_2(xsmsubadp, 0x04, 0x06, 0, PPC2_VSX)
7976GEN_VSX_HELPER_2(xsmsubmdp, 0x04, 0x07, 0, PPC2_VSX)
7977GEN_VSX_HELPER_2(xsnmaddadp, 0x04, 0x14, 0, PPC2_VSX)
7978GEN_VSX_HELPER_2(xsnmaddmdp, 0x04, 0x15, 0, PPC2_VSX)
7979GEN_VSX_HELPER_2(xsnmsubadp, 0x04, 0x16, 0, PPC2_VSX)
7980GEN_VSX_HELPER_2(xsnmsubmdp, 0x04, 0x17, 0, PPC2_VSX)
4f17e9c7
TM
7981GEN_VSX_HELPER_2(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX)
7982GEN_VSX_HELPER_2(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX)
959e9c9d
TM
7983GEN_VSX_HELPER_2(xsmaxdp, 0x00, 0x14, 0, PPC2_VSX)
7984GEN_VSX_HELPER_2(xsmindp, 0x00, 0x15, 0, PPC2_VSX)
ed8ac568 7985GEN_VSX_HELPER_2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX)
7ee19fb9 7986GEN_VSX_HELPER_XT_XB_ENV(xscvdpspn, 0x16, 0x10, 0, PPC2_VSX207)
ed8ac568 7987GEN_VSX_HELPER_2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX)
7ee19fb9 7988GEN_VSX_HELPER_XT_XB_ENV(xscvspdpn, 0x16, 0x14, 0, PPC2_VSX207)
5177d2ca
TM
7989GEN_VSX_HELPER_2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX)
7990GEN_VSX_HELPER_2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX)
7991GEN_VSX_HELPER_2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX)
7992GEN_VSX_HELPER_2(xscvdpuxws, 0x10, 0x04, 0, PPC2_VSX)
7993GEN_VSX_HELPER_2(xscvsxddp, 0x10, 0x17, 0, PPC2_VSX)
7994GEN_VSX_HELPER_2(xscvuxddp, 0x10, 0x16, 0, PPC2_VSX)
88e33d08
TM
7995GEN_VSX_HELPER_2(xsrdpi, 0x12, 0x04, 0, PPC2_VSX)
7996GEN_VSX_HELPER_2(xsrdpic, 0x16, 0x06, 0, PPC2_VSX)
7997GEN_VSX_HELPER_2(xsrdpim, 0x12, 0x07, 0, PPC2_VSX)
7998GEN_VSX_HELPER_2(xsrdpip, 0x12, 0x06, 0, PPC2_VSX)
7999GEN_VSX_HELPER_2(xsrdpiz, 0x12, 0x05, 0, PPC2_VSX)
3d1140bf 8000GEN_VSX_HELPER_XT_XB_ENV(xsrsp, 0x12, 0x11, 0, PPC2_VSX207)
ee6e02c0 8001
3fd0aadf
TM
8002GEN_VSX_HELPER_2(xsaddsp, 0x00, 0x00, 0, PPC2_VSX207)
8003GEN_VSX_HELPER_2(xssubsp, 0x00, 0x01, 0, PPC2_VSX207)
ab9408a2 8004GEN_VSX_HELPER_2(xsmulsp, 0x00, 0x02, 0, PPC2_VSX207)
b24d0b47 8005GEN_VSX_HELPER_2(xsdivsp, 0x00, 0x03, 0, PPC2_VSX207)
2c0c52ae 8006GEN_VSX_HELPER_2(xsresp, 0x14, 0x01, 0, PPC2_VSX207)
cea4e574 8007GEN_VSX_HELPER_2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207)
968e76bc 8008GEN_VSX_HELPER_2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_VSX207)
f53f81e0
TM
8009GEN_VSX_HELPER_2(xsmaddasp, 0x04, 0x00, 0, PPC2_VSX207)
8010GEN_VSX_HELPER_2(xsmaddmsp, 0x04, 0x01, 0, PPC2_VSX207)
8011GEN_VSX_HELPER_2(xsmsubasp, 0x04, 0x02, 0, PPC2_VSX207)
8012GEN_VSX_HELPER_2(xsmsubmsp, 0x04, 0x03, 0, PPC2_VSX207)
8013GEN_VSX_HELPER_2(xsnmaddasp, 0x04, 0x10, 0, PPC2_VSX207)
8014GEN_VSX_HELPER_2(xsnmaddmsp, 0x04, 0x11, 0, PPC2_VSX207)
8015GEN_VSX_HELPER_2(xsnmsubasp, 0x04, 0x12, 0, PPC2_VSX207)
8016GEN_VSX_HELPER_2(xsnmsubmsp, 0x04, 0x13, 0, PPC2_VSX207)
74698350
TM
8017GEN_VSX_HELPER_2(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207)
8018GEN_VSX_HELPER_2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207)
3fd0aadf 8019
ee6e02c0
TM
8020GEN_VSX_HELPER_2(xvadddp, 0x00, 0x0C, 0, PPC2_VSX)
8021GEN_VSX_HELPER_2(xvsubdp, 0x00, 0x0D, 0, PPC2_VSX)
5e591d88 8022GEN_VSX_HELPER_2(xvmuldp, 0x00, 0x0E, 0, PPC2_VSX)
4b98eeef 8023GEN_VSX_HELPER_2(xvdivdp, 0x00, 0x0F, 0, PPC2_VSX)
2009227f 8024GEN_VSX_HELPER_2(xvredp, 0x14, 0x0D, 0, PPC2_VSX)
d32404fe 8025GEN_VSX_HELPER_2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX)
d3f9df8f 8026GEN_VSX_HELPER_2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX)
bc80838f 8027GEN_VSX_HELPER_2(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX)
5cb151ac 8028GEN_VSX_HELPER_2(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX)
595c6eef
TM
8029GEN_VSX_HELPER_2(xvmaddadp, 0x04, 0x0C, 0, PPC2_VSX)
8030GEN_VSX_HELPER_2(xvmaddmdp, 0x04, 0x0D, 0, PPC2_VSX)
8031GEN_VSX_HELPER_2(xvmsubadp, 0x04, 0x0E, 0, PPC2_VSX)
8032GEN_VSX_HELPER_2(xvmsubmdp, 0x04, 0x0F, 0, PPC2_VSX)
8033GEN_VSX_HELPER_2(xvnmaddadp, 0x04, 0x1C, 0, PPC2_VSX)
8034GEN_VSX_HELPER_2(xvnmaddmdp, 0x04, 0x1D, 0, PPC2_VSX)
8035GEN_VSX_HELPER_2(xvnmsubadp, 0x04, 0x1E, 0, PPC2_VSX)
8036GEN_VSX_HELPER_2(xvnmsubmdp, 0x04, 0x1F, 0, PPC2_VSX)
959e9c9d
TM
8037GEN_VSX_HELPER_2(xvmaxdp, 0x00, 0x1C, 0, PPC2_VSX)
8038GEN_VSX_HELPER_2(xvmindp, 0x00, 0x1D, 0, PPC2_VSX)
354a6dec
TM
8039GEN_VSX_HELPER_2(xvcmpeqdp, 0x0C, 0x0C, 0, PPC2_VSX)
8040GEN_VSX_HELPER_2(xvcmpgtdp, 0x0C, 0x0D, 0, PPC2_VSX)
8041GEN_VSX_HELPER_2(xvcmpgedp, 0x0C, 0x0E, 0, PPC2_VSX)
ed8ac568 8042GEN_VSX_HELPER_2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX)
5177d2ca
TM
8043GEN_VSX_HELPER_2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX)
8044GEN_VSX_HELPER_2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX)
8045GEN_VSX_HELPER_2(xvcvdpuxds, 0x10, 0x1C, 0, PPC2_VSX)
8046GEN_VSX_HELPER_2(xvcvdpuxws, 0x10, 0x0C, 0, PPC2_VSX)
8047GEN_VSX_HELPER_2(xvcvsxddp, 0x10, 0x1F, 0, PPC2_VSX)
8048GEN_VSX_HELPER_2(xvcvuxddp, 0x10, 0x1E, 0, PPC2_VSX)
8049GEN_VSX_HELPER_2(xvcvsxwdp, 0x10, 0x0F, 0, PPC2_VSX)
8050GEN_VSX_HELPER_2(xvcvuxwdp, 0x10, 0x0E, 0, PPC2_VSX)
88e33d08
TM
8051GEN_VSX_HELPER_2(xvrdpi, 0x12, 0x0C, 0, PPC2_VSX)
8052GEN_VSX_HELPER_2(xvrdpic, 0x16, 0x0E, 0, PPC2_VSX)
8053GEN_VSX_HELPER_2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX)
8054GEN_VSX_HELPER_2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX)
8055GEN_VSX_HELPER_2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX)
ee6e02c0
TM
8056
8057GEN_VSX_HELPER_2(xvaddsp, 0x00, 0x08, 0, PPC2_VSX)
8058GEN_VSX_HELPER_2(xvsubsp, 0x00, 0x09, 0, PPC2_VSX)
5e591d88 8059GEN_VSX_HELPER_2(xvmulsp, 0x00, 0x0A, 0, PPC2_VSX)
4b98eeef 8060GEN_VSX_HELPER_2(xvdivsp, 0x00, 0x0B, 0, PPC2_VSX)
2009227f 8061GEN_VSX_HELPER_2(xvresp, 0x14, 0x09, 0, PPC2_VSX)
d32404fe 8062GEN_VSX_HELPER_2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX)
d3f9df8f 8063GEN_VSX_HELPER_2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX)
bc80838f 8064GEN_VSX_HELPER_2(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX)
5cb151ac 8065GEN_VSX_HELPER_2(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX)
595c6eef
TM
8066GEN_VSX_HELPER_2(xvmaddasp, 0x04, 0x08, 0, PPC2_VSX)
8067GEN_VSX_HELPER_2(xvmaddmsp, 0x04, 0x09, 0, PPC2_VSX)
8068GEN_VSX_HELPER_2(xvmsubasp, 0x04, 0x0A, 0, PPC2_VSX)
8069GEN_VSX_HELPER_2(xvmsubmsp, 0x04, 0x0B, 0, PPC2_VSX)
8070GEN_VSX_HELPER_2(xvnmaddasp, 0x04, 0x18, 0, PPC2_VSX)
8071GEN_VSX_HELPER_2(xvnmaddmsp, 0x04, 0x19, 0, PPC2_VSX)
8072GEN_VSX_HELPER_2(xvnmsubasp, 0x04, 0x1A, 0, PPC2_VSX)
8073GEN_VSX_HELPER_2(xvnmsubmsp, 0x04, 0x1B, 0, PPC2_VSX)
959e9c9d
TM
8074GEN_VSX_HELPER_2(xvmaxsp, 0x00, 0x18, 0, PPC2_VSX)
8075GEN_VSX_HELPER_2(xvminsp, 0x00, 0x19, 0, PPC2_VSX)
354a6dec
TM
8076GEN_VSX_HELPER_2(xvcmpeqsp, 0x0C, 0x08, 0, PPC2_VSX)
8077GEN_VSX_HELPER_2(xvcmpgtsp, 0x0C, 0x09, 0, PPC2_VSX)
8078GEN_VSX_HELPER_2(xvcmpgesp, 0x0C, 0x0A, 0, PPC2_VSX)
ed8ac568 8079GEN_VSX_HELPER_2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX)
5177d2ca
TM
8080GEN_VSX_HELPER_2(xvcvspsxds, 0x10, 0x19, 0, PPC2_VSX)
8081GEN_VSX_HELPER_2(xvcvspsxws, 0x10, 0x09, 0, PPC2_VSX)
8082GEN_VSX_HELPER_2(xvcvspuxds, 0x10, 0x18, 0, PPC2_VSX)
8083GEN_VSX_HELPER_2(xvcvspuxws, 0x10, 0x08, 0, PPC2_VSX)
8084GEN_VSX_HELPER_2(xvcvsxdsp, 0x10, 0x1B, 0, PPC2_VSX)
8085GEN_VSX_HELPER_2(xvcvuxdsp, 0x10, 0x1A, 0, PPC2_VSX)
8086GEN_VSX_HELPER_2(xvcvsxwsp, 0x10, 0x0B, 0, PPC2_VSX)
8087GEN_VSX_HELPER_2(xvcvuxwsp, 0x10, 0x0A, 0, PPC2_VSX)
88e33d08
TM
8088GEN_VSX_HELPER_2(xvrspi, 0x12, 0x08, 0, PPC2_VSX)
8089GEN_VSX_HELPER_2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX)
8090GEN_VSX_HELPER_2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX)
8091GEN_VSX_HELPER_2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX)
8092GEN_VSX_HELPER_2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX)
ee6e02c0 8093
79ca8a6a
TM
8094#define VSX_LOGICAL(name, tcg_op) \
8095static void glue(gen_, name)(DisasContext * ctx) \
8096 { \
8097 if (unlikely(!ctx->vsx_enabled)) { \
8098 gen_exception(ctx, POWERPC_EXCP_VSXU); \
8099 return; \
8100 } \
8101 tcg_op(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)), \
8102 cpu_vsrh(xB(ctx->opcode))); \
8103 tcg_op(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)), \
8104 cpu_vsrl(xB(ctx->opcode))); \
8105 }
8106
f976b09e
AG
8107VSX_LOGICAL(xxland, tcg_gen_and_i64)
8108VSX_LOGICAL(xxlandc, tcg_gen_andc_i64)
8109VSX_LOGICAL(xxlor, tcg_gen_or_i64)
8110VSX_LOGICAL(xxlxor, tcg_gen_xor_i64)
8111VSX_LOGICAL(xxlnor, tcg_gen_nor_i64)
67a33f37
TM
8112VSX_LOGICAL(xxleqv, tcg_gen_eqv_i64)
8113VSX_LOGICAL(xxlnand, tcg_gen_nand_i64)
8114VSX_LOGICAL(xxlorc, tcg_gen_orc_i64)
df020ce0 8115
ce577d2e
TM
8116#define VSX_XXMRG(name, high) \
8117static void glue(gen_, name)(DisasContext * ctx) \
8118 { \
8119 TCGv_i64 a0, a1, b0, b1; \
8120 if (unlikely(!ctx->vsx_enabled)) { \
8121 gen_exception(ctx, POWERPC_EXCP_VSXU); \
8122 return; \
8123 } \
f976b09e
AG
8124 a0 = tcg_temp_new_i64(); \
8125 a1 = tcg_temp_new_i64(); \
8126 b0 = tcg_temp_new_i64(); \
8127 b1 = tcg_temp_new_i64(); \
ce577d2e
TM
8128 if (high) { \
8129 tcg_gen_mov_i64(a0, cpu_vsrh(xA(ctx->opcode))); \
8130 tcg_gen_mov_i64(a1, cpu_vsrh(xA(ctx->opcode))); \
8131 tcg_gen_mov_i64(b0, cpu_vsrh(xB(ctx->opcode))); \
8132 tcg_gen_mov_i64(b1, cpu_vsrh(xB(ctx->opcode))); \
8133 } else { \
8134 tcg_gen_mov_i64(a0, cpu_vsrl(xA(ctx->opcode))); \
8135 tcg_gen_mov_i64(a1, cpu_vsrl(xA(ctx->opcode))); \
8136 tcg_gen_mov_i64(b0, cpu_vsrl(xB(ctx->opcode))); \
8137 tcg_gen_mov_i64(b1, cpu_vsrl(xB(ctx->opcode))); \
8138 } \
8139 tcg_gen_shri_i64(a0, a0, 32); \
8140 tcg_gen_shri_i64(b0, b0, 32); \
8141 tcg_gen_deposit_i64(cpu_vsrh(xT(ctx->opcode)), \
8142 b0, a0, 32, 32); \
8143 tcg_gen_deposit_i64(cpu_vsrl(xT(ctx->opcode)), \
8144 b1, a1, 32, 32); \
f976b09e
AG
8145 tcg_temp_free_i64(a0); \
8146 tcg_temp_free_i64(a1); \
8147 tcg_temp_free_i64(b0); \
8148 tcg_temp_free_i64(b1); \
ce577d2e
TM
8149 }
8150
8151VSX_XXMRG(xxmrghw, 1)
8152VSX_XXMRG(xxmrglw, 0)
8153
551e3ef7
TM
8154static void gen_xxsel(DisasContext * ctx)
8155{
8156 TCGv_i64 a, b, c;
8157 if (unlikely(!ctx->vsx_enabled)) {
8158 gen_exception(ctx, POWERPC_EXCP_VSXU);
8159 return;
8160 }
f976b09e
AG
8161 a = tcg_temp_new_i64();
8162 b = tcg_temp_new_i64();
8163 c = tcg_temp_new_i64();
551e3ef7
TM
8164
8165 tcg_gen_mov_i64(a, cpu_vsrh(xA(ctx->opcode)));
8166 tcg_gen_mov_i64(b, cpu_vsrh(xB(ctx->opcode)));
8167 tcg_gen_mov_i64(c, cpu_vsrh(xC(ctx->opcode)));
8168
8169 tcg_gen_and_i64(b, b, c);
8170 tcg_gen_andc_i64(a, a, c);
8171 tcg_gen_or_i64(cpu_vsrh(xT(ctx->opcode)), a, b);
8172
8173 tcg_gen_mov_i64(a, cpu_vsrl(xA(ctx->opcode)));
8174 tcg_gen_mov_i64(b, cpu_vsrl(xB(ctx->opcode)));
8175 tcg_gen_mov_i64(c, cpu_vsrl(xC(ctx->opcode)));
8176
8177 tcg_gen_and_i64(b, b, c);
8178 tcg_gen_andc_i64(a, a, c);
8179 tcg_gen_or_i64(cpu_vsrl(xT(ctx->opcode)), a, b);
8180
f976b09e
AG
8181 tcg_temp_free_i64(a);
8182 tcg_temp_free_i64(b);
8183 tcg_temp_free_i64(c);
551e3ef7
TM
8184}
8185
76c15fe0
TM
8186static void gen_xxspltw(DisasContext *ctx)
8187{
8188 TCGv_i64 b, b2;
8189 TCGv_i64 vsr = (UIM(ctx->opcode) & 2) ?
8190 cpu_vsrl(xB(ctx->opcode)) :
8191 cpu_vsrh(xB(ctx->opcode));
8192
8193 if (unlikely(!ctx->vsx_enabled)) {
8194 gen_exception(ctx, POWERPC_EXCP_VSXU);
8195 return;
8196 }
8197
f976b09e
AG
8198 b = tcg_temp_new_i64();
8199 b2 = tcg_temp_new_i64();
76c15fe0
TM
8200
8201 if (UIM(ctx->opcode) & 1) {
8202 tcg_gen_ext32u_i64(b, vsr);
8203 } else {
8204 tcg_gen_shri_i64(b, vsr, 32);
8205 }
8206
8207 tcg_gen_shli_i64(b2, b, 32);
8208 tcg_gen_or_i64(cpu_vsrh(xT(ctx->opcode)), b, b2);
8209 tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
8210
f976b09e
AG
8211 tcg_temp_free_i64(b);
8212 tcg_temp_free_i64(b2);
76c15fe0
TM
8213}
8214
acc42968
TM
8215static void gen_xxsldwi(DisasContext *ctx)
8216{
8217 TCGv_i64 xth, xtl;
8218 if (unlikely(!ctx->vsx_enabled)) {
8219 gen_exception(ctx, POWERPC_EXCP_VSXU);
8220 return;
8221 }
f976b09e
AG
8222 xth = tcg_temp_new_i64();
8223 xtl = tcg_temp_new_i64();
acc42968
TM
8224
8225 switch (SHW(ctx->opcode)) {
8226 case 0: {
8227 tcg_gen_mov_i64(xth, cpu_vsrh(xA(ctx->opcode)));
8228 tcg_gen_mov_i64(xtl, cpu_vsrl(xA(ctx->opcode)));
8229 break;
8230 }
8231 case 1: {
f976b09e 8232 TCGv_i64 t0 = tcg_temp_new_i64();
acc42968
TM
8233 tcg_gen_mov_i64(xth, cpu_vsrh(xA(ctx->opcode)));
8234 tcg_gen_shli_i64(xth, xth, 32);
8235 tcg_gen_mov_i64(t0, cpu_vsrl(xA(ctx->opcode)));
8236 tcg_gen_shri_i64(t0, t0, 32);
8237 tcg_gen_or_i64(xth, xth, t0);
8238 tcg_gen_mov_i64(xtl, cpu_vsrl(xA(ctx->opcode)));
8239 tcg_gen_shli_i64(xtl, xtl, 32);
8240 tcg_gen_mov_i64(t0, cpu_vsrh(xB(ctx->opcode)));
8241 tcg_gen_shri_i64(t0, t0, 32);
8242 tcg_gen_or_i64(xtl, xtl, t0);
f976b09e 8243 tcg_temp_free_i64(t0);
acc42968
TM
8244 break;
8245 }
8246 case 2: {
8247 tcg_gen_mov_i64(xth, cpu_vsrl(xA(ctx->opcode)));
8248 tcg_gen_mov_i64(xtl, cpu_vsrh(xB(ctx->opcode)));
8249 break;
8250 }
8251 case 3: {
f976b09e 8252 TCGv_i64 t0 = tcg_temp_new_i64();
acc42968
TM
8253 tcg_gen_mov_i64(xth, cpu_vsrl(xA(ctx->opcode)));
8254 tcg_gen_shli_i64(xth, xth, 32);
8255 tcg_gen_mov_i64(t0, cpu_vsrh(xB(ctx->opcode)));
8256 tcg_gen_shri_i64(t0, t0, 32);
8257 tcg_gen_or_i64(xth, xth, t0);
8258 tcg_gen_mov_i64(xtl, cpu_vsrh(xB(ctx->opcode)));
8259 tcg_gen_shli_i64(xtl, xtl, 32);
8260 tcg_gen_mov_i64(t0, cpu_vsrl(xB(ctx->opcode)));
8261 tcg_gen_shri_i64(t0, t0, 32);
8262 tcg_gen_or_i64(xtl, xtl, t0);
f976b09e 8263 tcg_temp_free_i64(t0);
acc42968
TM
8264 break;
8265 }
8266 }
8267
8268 tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xth);
8269 tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xtl);
8270
f976b09e
AG
8271 tcg_temp_free_i64(xth);
8272 tcg_temp_free_i64(xtl);
acc42968
TM
8273}
8274
f0b01f02
TM
8275/*** Decimal Floating Point ***/
8276
8277static inline TCGv_ptr gen_fprp_ptr(int reg)
8278{
8279 TCGv_ptr r = tcg_temp_new_ptr();
8280 tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, fpr[reg]));
8281 return r;
8282}
8283
f0b01f02
TM
8284#define GEN_DFP_T_A_B_Rc(name) \
8285static void gen_##name(DisasContext *ctx) \
8286{ \
8287 TCGv_ptr rd, ra, rb; \
8288 if (unlikely(!ctx->fpu_enabled)) { \
8289 gen_exception(ctx, POWERPC_EXCP_FPU); \
8290 return; \
8291 } \
8292 gen_update_nip(ctx, ctx->nip - 4); \
8293 rd = gen_fprp_ptr(rD(ctx->opcode)); \
8294 ra = gen_fprp_ptr(rA(ctx->opcode)); \
8295 rb = gen_fprp_ptr(rB(ctx->opcode)); \
8296 gen_helper_##name(cpu_env, rd, ra, rb); \
8297 if (unlikely(Rc(ctx->opcode) != 0)) { \
e57d0202 8298 gen_set_cr1_from_fpscr(ctx); \
f0b01f02
TM
8299 } \
8300 tcg_temp_free_ptr(rd); \
8301 tcg_temp_free_ptr(ra); \
8302 tcg_temp_free_ptr(rb); \
8303}
8304
8305#define GEN_DFP_BF_A_B(name) \
8306static void gen_##name(DisasContext *ctx) \
8307{ \
8308 TCGv_ptr ra, rb; \
8309 if (unlikely(!ctx->fpu_enabled)) { \
8310 gen_exception(ctx, POWERPC_EXCP_FPU); \
8311 return; \
8312 } \
8313 gen_update_nip(ctx, ctx->nip - 4); \
8314 ra = gen_fprp_ptr(rA(ctx->opcode)); \
8315 rb = gen_fprp_ptr(rB(ctx->opcode)); \
8316 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
8317 cpu_env, ra, rb); \
8318 tcg_temp_free_ptr(ra); \
8319 tcg_temp_free_ptr(rb); \
8320}
8321
8322#define GEN_DFP_BF_A_DCM(name) \
8323static void gen_##name(DisasContext *ctx) \
8324{ \
8325 TCGv_ptr ra; \
8326 TCGv_i32 dcm; \
8327 if (unlikely(!ctx->fpu_enabled)) { \
8328 gen_exception(ctx, POWERPC_EXCP_FPU); \
8329 return; \
8330 } \
8331 gen_update_nip(ctx, ctx->nip - 4); \
8332 ra = gen_fprp_ptr(rA(ctx->opcode)); \
8333 dcm = tcg_const_i32(DCM(ctx->opcode)); \
8334 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
8335 cpu_env, ra, dcm); \
8336 tcg_temp_free_ptr(ra); \
8337 tcg_temp_free_i32(dcm); \
8338}
8339
8340#define GEN_DFP_T_B_U32_U32_Rc(name, u32f1, u32f2) \
8341static void gen_##name(DisasContext *ctx) \
8342{ \
8343 TCGv_ptr rt, rb; \
8344 TCGv_i32 u32_1, u32_2; \
8345 if (unlikely(!ctx->fpu_enabled)) { \
8346 gen_exception(ctx, POWERPC_EXCP_FPU); \
8347 return; \
8348 } \
8349 gen_update_nip(ctx, ctx->nip - 4); \
8350 rt = gen_fprp_ptr(rD(ctx->opcode)); \
8351 rb = gen_fprp_ptr(rB(ctx->opcode)); \
8352 u32_1 = tcg_const_i32(u32f1(ctx->opcode)); \
8353 u32_2 = tcg_const_i32(u32f2(ctx->opcode)); \
8354 gen_helper_##name(cpu_env, rt, rb, u32_1, u32_2); \
8355 if (unlikely(Rc(ctx->opcode) != 0)) { \
e57d0202 8356 gen_set_cr1_from_fpscr(ctx); \
f0b01f02
TM
8357 } \
8358 tcg_temp_free_ptr(rt); \
8359 tcg_temp_free_ptr(rb); \
8360 tcg_temp_free_i32(u32_1); \
8361 tcg_temp_free_i32(u32_2); \
8362}
8363
8364#define GEN_DFP_T_A_B_I32_Rc(name, i32fld) \
8365static void gen_##name(DisasContext *ctx) \
8366{ \
8367 TCGv_ptr rt, ra, rb; \
8368 TCGv_i32 i32; \
8369 if (unlikely(!ctx->fpu_enabled)) { \
8370 gen_exception(ctx, POWERPC_EXCP_FPU); \
8371 return; \
8372 } \
8373 gen_update_nip(ctx, ctx->nip - 4); \
8374 rt = gen_fprp_ptr(rD(ctx->opcode)); \
8375 ra = gen_fprp_ptr(rA(ctx->opcode)); \
8376 rb = gen_fprp_ptr(rB(ctx->opcode)); \
8377 i32 = tcg_const_i32(i32fld(ctx->opcode)); \
8378 gen_helper_##name(cpu_env, rt, ra, rb, i32); \
8379 if (unlikely(Rc(ctx->opcode) != 0)) { \
e57d0202 8380 gen_set_cr1_from_fpscr(ctx); \
f0b01f02
TM
8381 } \
8382 tcg_temp_free_ptr(rt); \
8383 tcg_temp_free_ptr(rb); \
8384 tcg_temp_free_ptr(ra); \
8385 tcg_temp_free_i32(i32); \
8386 }
8387
8388#define GEN_DFP_T_B_Rc(name) \
8389static void gen_##name(DisasContext *ctx) \
8390{ \
8391 TCGv_ptr rt, rb; \
8392 if (unlikely(!ctx->fpu_enabled)) { \
8393 gen_exception(ctx, POWERPC_EXCP_FPU); \
8394 return; \
8395 } \
8396 gen_update_nip(ctx, ctx->nip - 4); \
8397 rt = gen_fprp_ptr(rD(ctx->opcode)); \
8398 rb = gen_fprp_ptr(rB(ctx->opcode)); \
8399 gen_helper_##name(cpu_env, rt, rb); \
8400 if (unlikely(Rc(ctx->opcode) != 0)) { \
e57d0202 8401 gen_set_cr1_from_fpscr(ctx); \
f0b01f02
TM
8402 } \
8403 tcg_temp_free_ptr(rt); \
8404 tcg_temp_free_ptr(rb); \
8405 }
8406
8407#define GEN_DFP_T_FPR_I32_Rc(name, fprfld, i32fld) \
8408static void gen_##name(DisasContext *ctx) \
8409{ \
8410 TCGv_ptr rt, rs; \
8411 TCGv_i32 i32; \
8412 if (unlikely(!ctx->fpu_enabled)) { \
8413 gen_exception(ctx, POWERPC_EXCP_FPU); \
8414 return; \
8415 } \
8416 gen_update_nip(ctx, ctx->nip - 4); \
8417 rt = gen_fprp_ptr(rD(ctx->opcode)); \
8418 rs = gen_fprp_ptr(fprfld(ctx->opcode)); \
8419 i32 = tcg_const_i32(i32fld(ctx->opcode)); \
8420 gen_helper_##name(cpu_env, rt, rs, i32); \
8421 if (unlikely(Rc(ctx->opcode) != 0)) { \
e57d0202 8422 gen_set_cr1_from_fpscr(ctx); \
f0b01f02
TM
8423 } \
8424 tcg_temp_free_ptr(rt); \
8425 tcg_temp_free_ptr(rs); \
8426 tcg_temp_free_i32(i32); \
8427}
ce577d2e 8428
a9d7ba03
TM
8429GEN_DFP_T_A_B_Rc(dadd)
8430GEN_DFP_T_A_B_Rc(daddq)
2128f8a5
TM
8431GEN_DFP_T_A_B_Rc(dsub)
8432GEN_DFP_T_A_B_Rc(dsubq)
8de6a1cc
TM
8433GEN_DFP_T_A_B_Rc(dmul)
8434GEN_DFP_T_A_B_Rc(dmulq)
9024ff40
TM
8435GEN_DFP_T_A_B_Rc(ddiv)
8436GEN_DFP_T_A_B_Rc(ddivq)
5833505b
TM
8437GEN_DFP_BF_A_B(dcmpu)
8438GEN_DFP_BF_A_B(dcmpuq)
8439GEN_DFP_BF_A_B(dcmpo)
8440GEN_DFP_BF_A_B(dcmpoq)
e601c1ee
TM
8441GEN_DFP_BF_A_DCM(dtstdc)
8442GEN_DFP_BF_A_DCM(dtstdcq)
1bf9c0e1
TM
8443GEN_DFP_BF_A_DCM(dtstdg)
8444GEN_DFP_BF_A_DCM(dtstdgq)
f3d2b0bc
TM
8445GEN_DFP_BF_A_B(dtstex)
8446GEN_DFP_BF_A_B(dtstexq)
f6022a76
TM
8447GEN_DFP_BF_A_B(dtstsf)
8448GEN_DFP_BF_A_B(dtstsfq)
5826ebe2
TM
8449GEN_DFP_T_B_U32_U32_Rc(dquai, SIMM5, RMC)
8450GEN_DFP_T_B_U32_U32_Rc(dquaiq, SIMM5, RMC)
8451GEN_DFP_T_A_B_I32_Rc(dqua, RMC)
8452GEN_DFP_T_A_B_I32_Rc(dquaq, RMC)
512918aa
TM
8453GEN_DFP_T_A_B_I32_Rc(drrnd, RMC)
8454GEN_DFP_T_A_B_I32_Rc(drrndq, RMC)
97c0d930
TM
8455GEN_DFP_T_B_U32_U32_Rc(drintx, FPW, RMC)
8456GEN_DFP_T_B_U32_U32_Rc(drintxq, FPW, RMC)
8457GEN_DFP_T_B_U32_U32_Rc(drintn, FPW, RMC)
8458GEN_DFP_T_B_U32_U32_Rc(drintnq, FPW, RMC)
290d9ee5
TM
8459GEN_DFP_T_B_Rc(dctdp)
8460GEN_DFP_T_B_Rc(dctqpq)
ca603eb4
TM
8461GEN_DFP_T_B_Rc(drsp)
8462GEN_DFP_T_B_Rc(drdpq)
f1214193
TM
8463GEN_DFP_T_B_Rc(dcffix)
8464GEN_DFP_T_B_Rc(dcffixq)
bea0dd79
TM
8465GEN_DFP_T_B_Rc(dctfix)
8466GEN_DFP_T_B_Rc(dctfixq)
7796676f
TM
8467GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP)
8468GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP)
013c3ac0
TM
8469GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP)
8470GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP)
e8a48460
TM
8471GEN_DFP_T_B_Rc(dxex)
8472GEN_DFP_T_B_Rc(dxexq)
297666eb
TM
8473GEN_DFP_T_A_B_Rc(diex)
8474GEN_DFP_T_A_B_Rc(diexq)
804e654a
TM
8475GEN_DFP_T_FPR_I32_Rc(dscli, rA, DCM)
8476GEN_DFP_T_FPR_I32_Rc(dscliq, rA, DCM)
8477GEN_DFP_T_FPR_I32_Rc(dscri, rA, DCM)
8478GEN_DFP_T_FPR_I32_Rc(dscriq, rA, DCM)
8479
0487d6a8 8480/*** SPE extension ***/
0487d6a8 8481/* Register moves */
3cd7d1dd 8482
a0e13900
FC
8483static inline void gen_evmra(DisasContext *ctx)
8484{
8485
8486 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8487 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
8488 return;
8489 }
8490
a0e13900
FC
8491 TCGv_i64 tmp = tcg_temp_new_i64();
8492
8493 /* tmp := rA_lo + rA_hi << 32 */
13b6a455 8494 tcg_gen_concat_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
a0e13900
FC
8495
8496 /* spe_acc := tmp */
1328c2bf 8497 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
8498 tcg_temp_free_i64(tmp);
8499
8500 /* rD := rA */
13b6a455
AG
8501 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8502 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
a0e13900
FC
8503}
8504
636aa200
BS
8505static inline void gen_load_gpr64(TCGv_i64 t, int reg)
8506{
13b6a455 8507 tcg_gen_concat_tl_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
f78fb44e 8508}
3cd7d1dd 8509
636aa200
BS
8510static inline void gen_store_gpr64(int reg, TCGv_i64 t)
8511{
13b6a455 8512 tcg_gen_extr_i64_tl(cpu_gpr[reg], cpu_gprh[reg], t);
f78fb44e 8513}
3cd7d1dd 8514
70560da7 8515#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
99e300ef 8516static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
0487d6a8
JM
8517{ \
8518 if (Rc(ctx->opcode)) \
8519 gen_##name1(ctx); \
8520 else \
8521 gen_##name0(ctx); \
8522}
8523
8524/* Handler for undefined SPE opcodes */
636aa200 8525static inline void gen_speundef(DisasContext *ctx)
0487d6a8 8526{
e06fcd75 8527 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
0487d6a8
JM
8528}
8529
57951c27 8530/* SPE logic */
57951c27 8531#define GEN_SPEOP_LOGIC2(name, tcg_op) \
636aa200 8532static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
8533{ \
8534 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8535 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
8536 return; \
8537 } \
8538 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
8539 cpu_gpr[rB(ctx->opcode)]); \
8540 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
8541 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 8542}
57951c27
AJ
8543
8544GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
8545GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
8546GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
8547GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
8548GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
8549GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
8550GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
8551GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
0487d6a8 8552
57951c27 8553/* SPE logic immediate */
57951c27 8554#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
636aa200 8555static inline void gen_##name(DisasContext *ctx) \
3d3a6a0a 8556{ \
13b6a455 8557 TCGv_i32 t0; \
3d3a6a0a 8558 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8559 gen_exception(ctx, POWERPC_EXCP_SPEU); \
3d3a6a0a
AJ
8560 return; \
8561 } \
13b6a455
AG
8562 t0 = tcg_temp_new_i32(); \
8563 \
8564 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
8565 tcg_opi(t0, t0, rB(ctx->opcode)); \
8566 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
8567 \
8568 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
57951c27 8569 tcg_opi(t0, t0, rB(ctx->opcode)); \
13b6a455
AG
8570 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
8571 \
a7812ae4 8572 tcg_temp_free_i32(t0); \
3d3a6a0a 8573}
57951c27
AJ
8574GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
8575GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
8576GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
8577GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
0487d6a8 8578
57951c27 8579/* SPE arithmetic */
57951c27 8580#define GEN_SPEOP_ARITH1(name, tcg_op) \
636aa200 8581static inline void gen_##name(DisasContext *ctx) \
0487d6a8 8582{ \
13b6a455 8583 TCGv_i32 t0; \
0487d6a8 8584 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8585 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
8586 return; \
8587 } \
13b6a455
AG
8588 t0 = tcg_temp_new_i32(); \
8589 \
8590 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
57951c27 8591 tcg_op(t0, t0); \
13b6a455
AG
8592 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
8593 \
8594 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
8595 tcg_op(t0, t0); \
8596 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
8597 \
a7812ae4 8598 tcg_temp_free_i32(t0); \
57951c27 8599}
0487d6a8 8600
636aa200 8601static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
57951c27 8602{
42a268c2
RH
8603 TCGLabel *l1 = gen_new_label();
8604 TCGLabel *l2 = gen_new_label();
0487d6a8 8605
57951c27
AJ
8606 tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
8607 tcg_gen_neg_i32(ret, arg1);
8608 tcg_gen_br(l2);
8609 gen_set_label(l1);
a7812ae4 8610 tcg_gen_mov_i32(ret, arg1);
57951c27
AJ
8611 gen_set_label(l2);
8612}
8613GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
8614GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
8615GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
8616GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
636aa200 8617static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
0487d6a8 8618{
57951c27
AJ
8619 tcg_gen_addi_i32(ret, arg1, 0x8000);
8620 tcg_gen_ext16u_i32(ret, ret);
8621}
8622GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
a7812ae4
PB
8623GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
8624GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
0487d6a8 8625
57951c27 8626#define GEN_SPEOP_ARITH2(name, tcg_op) \
636aa200 8627static inline void gen_##name(DisasContext *ctx) \
0487d6a8 8628{ \
13b6a455 8629 TCGv_i32 t0, t1; \
0487d6a8 8630 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8631 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
8632 return; \
8633 } \
13b6a455
AG
8634 t0 = tcg_temp_new_i32(); \
8635 t1 = tcg_temp_new_i32(); \
8636 \
8637 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
8638 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
8639 tcg_op(t0, t0, t1); \
8640 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
8641 \
8642 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
8643 tcg_gen_trunc_tl_i32(t1, cpu_gprh[rB(ctx->opcode)]); \
8644 tcg_op(t0, t0, t1); \
8645 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
8646 \
a7812ae4
PB
8647 tcg_temp_free_i32(t0); \
8648 tcg_temp_free_i32(t1); \
0487d6a8 8649}
0487d6a8 8650
636aa200 8651static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 8652{
42a268c2
RH
8653 TCGLabel *l1 = gen_new_label();
8654 TCGLabel *l2 = gen_new_label();
8655 TCGv_i32 t0 = tcg_temp_local_new_i32();
0487d6a8 8656
57951c27
AJ
8657 /* No error here: 6 bits are used */
8658 tcg_gen_andi_i32(t0, arg2, 0x3F);
8659 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
8660 tcg_gen_shr_i32(ret, arg1, t0);
8661 tcg_gen_br(l2);
8662 gen_set_label(l1);
8663 tcg_gen_movi_i32(ret, 0);
0aef4261 8664 gen_set_label(l2);
a7812ae4 8665 tcg_temp_free_i32(t0);
57951c27
AJ
8666}
8667GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
636aa200 8668static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 8669{
42a268c2
RH
8670 TCGLabel *l1 = gen_new_label();
8671 TCGLabel *l2 = gen_new_label();
8672 TCGv_i32 t0 = tcg_temp_local_new_i32();
57951c27 8673
57951c27
AJ
8674 /* No error here: 6 bits are used */
8675 tcg_gen_andi_i32(t0, arg2, 0x3F);
8676 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
8677 tcg_gen_sar_i32(ret, arg1, t0);
8678 tcg_gen_br(l2);
8679 gen_set_label(l1);
8680 tcg_gen_movi_i32(ret, 0);
0aef4261 8681 gen_set_label(l2);
a7812ae4 8682 tcg_temp_free_i32(t0);
57951c27
AJ
8683}
8684GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
636aa200 8685static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 8686{
42a268c2
RH
8687 TCGLabel *l1 = gen_new_label();
8688 TCGLabel *l2 = gen_new_label();
8689 TCGv_i32 t0 = tcg_temp_local_new_i32();
57951c27 8690
57951c27
AJ
8691 /* No error here: 6 bits are used */
8692 tcg_gen_andi_i32(t0, arg2, 0x3F);
8693 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
8694 tcg_gen_shl_i32(ret, arg1, t0);
8695 tcg_gen_br(l2);
8696 gen_set_label(l1);
8697 tcg_gen_movi_i32(ret, 0);
e29ef9fa 8698 gen_set_label(l2);
a7812ae4 8699 tcg_temp_free_i32(t0);
57951c27
AJ
8700}
8701GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
636aa200 8702static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 8703{
a7812ae4 8704 TCGv_i32 t0 = tcg_temp_new_i32();
57951c27
AJ
8705 tcg_gen_andi_i32(t0, arg2, 0x1F);
8706 tcg_gen_rotl_i32(ret, arg1, t0);
a7812ae4 8707 tcg_temp_free_i32(t0);
57951c27
AJ
8708}
8709GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
636aa200 8710static inline void gen_evmergehi(DisasContext *ctx)
57951c27
AJ
8711{
8712 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8713 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
8714 return;
8715 }
13b6a455
AG
8716 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8717 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
57951c27
AJ
8718}
8719GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
636aa200 8720static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
0487d6a8 8721{
57951c27
AJ
8722 tcg_gen_sub_i32(ret, arg2, arg1);
8723}
8724GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
0487d6a8 8725
57951c27 8726/* SPE arithmetic immediate */
57951c27 8727#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
636aa200 8728static inline void gen_##name(DisasContext *ctx) \
57951c27 8729{ \
13b6a455 8730 TCGv_i32 t0; \
57951c27 8731 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8732 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
8733 return; \
8734 } \
13b6a455
AG
8735 t0 = tcg_temp_new_i32(); \
8736 \
8737 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
57951c27 8738 tcg_op(t0, t0, rA(ctx->opcode)); \
13b6a455
AG
8739 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
8740 \
8741 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rB(ctx->opcode)]); \
8742 tcg_op(t0, t0, rA(ctx->opcode)); \
8743 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
8744 \
a7812ae4 8745 tcg_temp_free_i32(t0); \
57951c27 8746}
57951c27
AJ
8747GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
8748GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
8749
8750/* SPE comparison */
57951c27 8751#define GEN_SPEOP_COMP(name, tcg_cond) \
636aa200 8752static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
8753{ \
8754 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8755 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
8756 return; \
8757 } \
42a268c2
RH
8758 TCGLabel *l1 = gen_new_label(); \
8759 TCGLabel *l2 = gen_new_label(); \
8760 TCGLabel *l3 = gen_new_label(); \
8761 TCGLabel *l4 = gen_new_label(); \
57951c27 8762 \
13b6a455
AG
8763 tcg_gen_ext32s_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
8764 tcg_gen_ext32s_tl(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8765 tcg_gen_ext32s_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
8766 tcg_gen_ext32s_tl(cpu_gprh[rB(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); \
8767 \
8768 tcg_gen_brcond_tl(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
57951c27 8769 cpu_gpr[rB(ctx->opcode)], l1); \
13b6a455 8770 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
57951c27
AJ
8771 tcg_gen_br(l2); \
8772 gen_set_label(l1); \
8773 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
8774 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
8775 gen_set_label(l2); \
13b6a455 8776 tcg_gen_brcond_tl(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
57951c27
AJ
8777 cpu_gprh[rB(ctx->opcode)], l3); \
8778 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
8779 ~(CRF_CH | CRF_CH_AND_CL)); \
8780 tcg_gen_br(l4); \
8781 gen_set_label(l3); \
8782 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
8783 CRF_CH | CRF_CH_OR_CL); \
8784 gen_set_label(l4); \
8785}
57951c27
AJ
8786GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
8787GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
8788GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
8789GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
8790GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
8791
8792/* SPE misc */
636aa200 8793static inline void gen_brinc(DisasContext *ctx)
57951c27
AJ
8794{
8795 /* Note: brinc is usable even if SPE is disabled */
a7812ae4
PB
8796 gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
8797 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
0487d6a8 8798}
636aa200 8799static inline void gen_evmergelo(DisasContext *ctx)
57951c27
AJ
8800{
8801 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8802 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
8803 return;
8804 }
13b6a455
AG
8805 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8806 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
57951c27 8807}
636aa200 8808static inline void gen_evmergehilo(DisasContext *ctx)
57951c27
AJ
8809{
8810 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8811 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
8812 return;
8813 }
13b6a455
AG
8814 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
8815 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
57951c27 8816}
636aa200 8817static inline void gen_evmergelohi(DisasContext *ctx)
57951c27
AJ
8818{
8819 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8820 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
8821 return;
8822 }
33890b3e 8823 if (rD(ctx->opcode) == rA(ctx->opcode)) {
13b6a455
AG
8824 TCGv tmp = tcg_temp_new();
8825 tcg_gen_mov_tl(tmp, cpu_gpr[rA(ctx->opcode)]);
8826 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8827 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], tmp);
8828 tcg_temp_free(tmp);
33890b3e 8829 } else {
13b6a455
AG
8830 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
8831 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
33890b3e 8832 }
57951c27 8833}
636aa200 8834static inline void gen_evsplati(DisasContext *ctx)
57951c27 8835{
ae01847f 8836 uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
0487d6a8 8837
13b6a455
AG
8838 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
8839 tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
57951c27 8840}
636aa200 8841static inline void gen_evsplatfi(DisasContext *ctx)
0487d6a8 8842{
ae01847f 8843 uint64_t imm = rA(ctx->opcode) << 27;
0487d6a8 8844
13b6a455
AG
8845 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm);
8846 tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm);
0487d6a8
JM
8847}
8848
636aa200 8849static inline void gen_evsel(DisasContext *ctx)
57951c27 8850{
42a268c2
RH
8851 TCGLabel *l1 = gen_new_label();
8852 TCGLabel *l2 = gen_new_label();
8853 TCGLabel *l3 = gen_new_label();
8854 TCGLabel *l4 = gen_new_label();
a7812ae4 8855 TCGv_i32 t0 = tcg_temp_local_new_i32();
42a268c2 8856
57951c27
AJ
8857 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
8858 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
57951c27 8859 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
57951c27
AJ
8860 tcg_gen_br(l2);
8861 gen_set_label(l1);
57951c27 8862 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
57951c27
AJ
8863 gen_set_label(l2);
8864 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
8865 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
57951c27 8866 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
57951c27
AJ
8867 tcg_gen_br(l4);
8868 gen_set_label(l3);
57951c27 8869 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
57951c27 8870 gen_set_label(l4);
a7812ae4 8871 tcg_temp_free_i32(t0);
57951c27 8872}
e8eaa2c0
BS
8873
8874static void gen_evsel0(DisasContext *ctx)
57951c27
AJ
8875{
8876 gen_evsel(ctx);
8877}
e8eaa2c0
BS
8878
8879static void gen_evsel1(DisasContext *ctx)
57951c27
AJ
8880{
8881 gen_evsel(ctx);
8882}
e8eaa2c0
BS
8883
8884static void gen_evsel2(DisasContext *ctx)
57951c27
AJ
8885{
8886 gen_evsel(ctx);
8887}
e8eaa2c0
BS
8888
8889static void gen_evsel3(DisasContext *ctx)
57951c27
AJ
8890{
8891 gen_evsel(ctx);
8892}
0487d6a8 8893
a0e13900
FC
8894/* Multiply */
8895
8896static inline void gen_evmwumi(DisasContext *ctx)
8897{
8898 TCGv_i64 t0, t1;
8899
8900 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8901 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
8902 return;
8903 }
8904
8905 t0 = tcg_temp_new_i64();
8906 t1 = tcg_temp_new_i64();
8907
8908 /* t0 := rA; t1 := rB */
a0e13900 8909 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
13b6a455 8910 tcg_gen_ext32u_i64(t0, t0);
a0e13900 8911 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
13b6a455 8912 tcg_gen_ext32u_i64(t1, t1);
a0e13900
FC
8913
8914 tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
8915
8916 gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
8917
8918 tcg_temp_free_i64(t0);
8919 tcg_temp_free_i64(t1);
8920}
8921
8922static inline void gen_evmwumia(DisasContext *ctx)
8923{
8924 TCGv_i64 tmp;
8925
8926 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8927 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
8928 return;
8929 }
8930
8931 gen_evmwumi(ctx); /* rD := rA * rB */
8932
8933 tmp = tcg_temp_new_i64();
8934
8935 /* acc := rD */
8936 gen_load_gpr64(tmp, rD(ctx->opcode));
1328c2bf 8937 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
8938 tcg_temp_free_i64(tmp);
8939}
8940
8941static inline void gen_evmwumiaa(DisasContext *ctx)
8942{
8943 TCGv_i64 acc;
8944 TCGv_i64 tmp;
8945
8946 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8947 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
8948 return;
8949 }
8950
8951 gen_evmwumi(ctx); /* rD := rA * rB */
8952
8953 acc = tcg_temp_new_i64();
8954 tmp = tcg_temp_new_i64();
8955
8956 /* tmp := rD */
8957 gen_load_gpr64(tmp, rD(ctx->opcode));
8958
8959 /* Load acc */
1328c2bf 8960 tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
8961
8962 /* acc := tmp + acc */
8963 tcg_gen_add_i64(acc, acc, tmp);
8964
8965 /* Store acc */
1328c2bf 8966 tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
8967
8968 /* rD := acc */
8969 gen_store_gpr64(rD(ctx->opcode), acc);
8970
8971 tcg_temp_free_i64(acc);
8972 tcg_temp_free_i64(tmp);
8973}
8974
8975static inline void gen_evmwsmi(DisasContext *ctx)
8976{
8977 TCGv_i64 t0, t1;
8978
8979 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8980 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
8981 return;
8982 }
8983
8984 t0 = tcg_temp_new_i64();
8985 t1 = tcg_temp_new_i64();
8986
8987 /* t0 := rA; t1 := rB */
13b6a455
AG
8988 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
8989 tcg_gen_ext32s_i64(t0, t0);
8990 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
8991 tcg_gen_ext32s_i64(t1, t1);
a0e13900
FC
8992
8993 tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
8994
8995 gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
8996
8997 tcg_temp_free_i64(t0);
8998 tcg_temp_free_i64(t1);
8999}
9000
9001static inline void gen_evmwsmia(DisasContext *ctx)
9002{
9003 TCGv_i64 tmp;
9004
9005 gen_evmwsmi(ctx); /* rD := rA * rB */
9006
9007 tmp = tcg_temp_new_i64();
9008
9009 /* acc := rD */
9010 gen_load_gpr64(tmp, rD(ctx->opcode));
1328c2bf 9011 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
9012
9013 tcg_temp_free_i64(tmp);
9014}
9015
9016static inline void gen_evmwsmiaa(DisasContext *ctx)
9017{
9018 TCGv_i64 acc = tcg_temp_new_i64();
9019 TCGv_i64 tmp = tcg_temp_new_i64();
9020
9021 gen_evmwsmi(ctx); /* rD := rA * rB */
9022
9023 acc = tcg_temp_new_i64();
9024 tmp = tcg_temp_new_i64();
9025
9026 /* tmp := rD */
9027 gen_load_gpr64(tmp, rD(ctx->opcode));
9028
9029 /* Load acc */
1328c2bf 9030 tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
9031
9032 /* acc := tmp + acc */
9033 tcg_gen_add_i64(acc, acc, tmp);
9034
9035 /* Store acc */
1328c2bf 9036 tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
9037
9038 /* rD := acc */
9039 gen_store_gpr64(rD(ctx->opcode), acc);
9040
9041 tcg_temp_free_i64(acc);
9042 tcg_temp_free_i64(tmp);
9043}
9044
70560da7
FC
9045GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9046GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9047GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9048GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9049GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
9050GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
9051GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
9052GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE); //
9053GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE);
9054GEN_SPE(speundef, evand, 0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
9055GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9056GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9057GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9058GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9059GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9060GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE);
9061GEN_SPE(speundef, evorc, 0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
9062GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9063GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9064GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE);
9065GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
9066GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9067GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE); //
9068GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
9069GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9070GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
9071GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
9072GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
9073GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE); ////
0487d6a8 9074
6a6ae23f 9075/* SPE load and stores */
636aa200 9076static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
6a6ae23f
AJ
9077{
9078 target_ulong uimm = rB(ctx->opcode);
9079
76db3ba4 9080 if (rA(ctx->opcode) == 0) {
6a6ae23f 9081 tcg_gen_movi_tl(EA, uimm << sh);
76db3ba4 9082 } else {
6a6ae23f 9083 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
c791fe84 9084 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
9085 tcg_gen_ext32u_tl(EA, EA);
9086 }
76db3ba4 9087 }
0487d6a8 9088}
6a6ae23f 9089
636aa200 9090static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
6a6ae23f 9091{
6a6ae23f 9092 TCGv_i64 t0 = tcg_temp_new_i64();
76db3ba4 9093 gen_qemu_ld64(ctx, t0, addr);
13b6a455 9094 gen_store_gpr64(rD(ctx->opcode), t0);
6a6ae23f 9095 tcg_temp_free_i64(t0);
0487d6a8 9096}
6a6ae23f 9097
636aa200 9098static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
6a6ae23f 9099{
76db3ba4
AJ
9100 gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
9101 gen_addr_add(ctx, addr, addr, 4);
9102 gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
0487d6a8 9103}
6a6ae23f 9104
636aa200 9105static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
9106{
9107 TCGv t0 = tcg_temp_new();
76db3ba4 9108 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 9109 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
76db3ba4
AJ
9110 gen_addr_add(ctx, addr, addr, 2);
9111 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 9112 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
76db3ba4
AJ
9113 gen_addr_add(ctx, addr, addr, 2);
9114 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 9115 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
76db3ba4
AJ
9116 gen_addr_add(ctx, addr, addr, 2);
9117 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 9118 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6a6ae23f 9119 tcg_temp_free(t0);
0487d6a8
JM
9120}
9121
636aa200 9122static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
9123{
9124 TCGv t0 = tcg_temp_new();
76db3ba4 9125 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
9126 tcg_gen_shli_tl(t0, t0, 16);
9127 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9128 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6a6ae23f 9129 tcg_temp_free(t0);
0487d6a8
JM
9130}
9131
636aa200 9132static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
9133{
9134 TCGv t0 = tcg_temp_new();
76db3ba4 9135 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
9136 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9137 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6a6ae23f 9138 tcg_temp_free(t0);
0487d6a8
JM
9139}
9140
636aa200 9141static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
9142{
9143 TCGv t0 = tcg_temp_new();
76db3ba4 9144 gen_qemu_ld16s(ctx, t0, addr);
6a6ae23f
AJ
9145 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9146 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6a6ae23f
AJ
9147 tcg_temp_free(t0);
9148}
9149
636aa200 9150static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
9151{
9152 TCGv t0 = tcg_temp_new();
76db3ba4 9153 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 9154 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
76db3ba4
AJ
9155 gen_addr_add(ctx, addr, addr, 2);
9156 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 9157 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
6a6ae23f
AJ
9158 tcg_temp_free(t0);
9159}
9160
636aa200 9161static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
6a6ae23f 9162{
76db3ba4
AJ
9163 gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
9164 gen_addr_add(ctx, addr, addr, 2);
9165 gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f
AJ
9166}
9167
636aa200 9168static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
6a6ae23f 9169{
76db3ba4
AJ
9170 gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
9171 gen_addr_add(ctx, addr, addr, 2);
9172 gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f
AJ
9173}
9174
636aa200 9175static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
9176{
9177 TCGv t0 = tcg_temp_new();
76db3ba4 9178 gen_qemu_ld32u(ctx, t0, addr);
6a6ae23f
AJ
9179 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
9180 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6a6ae23f
AJ
9181 tcg_temp_free(t0);
9182}
9183
636aa200 9184static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
9185{
9186 TCGv t0 = tcg_temp_new();
76db3ba4 9187 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
9188 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
9189 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
76db3ba4
AJ
9190 gen_addr_add(ctx, addr, addr, 2);
9191 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
9192 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
9193 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6a6ae23f
AJ
9194 tcg_temp_free(t0);
9195}
9196
636aa200 9197static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
6a6ae23f 9198{
6a6ae23f 9199 TCGv_i64 t0 = tcg_temp_new_i64();
13b6a455 9200 gen_load_gpr64(t0, rS(ctx->opcode));
76db3ba4 9201 gen_qemu_st64(ctx, t0, addr);
6a6ae23f 9202 tcg_temp_free_i64(t0);
6a6ae23f
AJ
9203}
9204
636aa200 9205static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
6a6ae23f 9206{
76db3ba4 9207 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
76db3ba4
AJ
9208 gen_addr_add(ctx, addr, addr, 4);
9209 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
9210}
9211
636aa200 9212static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
9213{
9214 TCGv t0 = tcg_temp_new();
6a6ae23f 9215 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
76db3ba4
AJ
9216 gen_qemu_st16(ctx, t0, addr);
9217 gen_addr_add(ctx, addr, addr, 2);
76db3ba4 9218 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
76db3ba4 9219 gen_addr_add(ctx, addr, addr, 2);
6a6ae23f 9220 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
76db3ba4 9221 gen_qemu_st16(ctx, t0, addr);
6a6ae23f 9222 tcg_temp_free(t0);
76db3ba4
AJ
9223 gen_addr_add(ctx, addr, addr, 2);
9224 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
9225}
9226
636aa200 9227static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
9228{
9229 TCGv t0 = tcg_temp_new();
6a6ae23f 9230 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
76db3ba4
AJ
9231 gen_qemu_st16(ctx, t0, addr);
9232 gen_addr_add(ctx, addr, addr, 2);
6a6ae23f 9233 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
76db3ba4 9234 gen_qemu_st16(ctx, t0, addr);
6a6ae23f
AJ
9235 tcg_temp_free(t0);
9236}
9237
636aa200 9238static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
6a6ae23f 9239{
76db3ba4 9240 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
76db3ba4
AJ
9241 gen_addr_add(ctx, addr, addr, 2);
9242 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
9243}
9244
636aa200 9245static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
6a6ae23f 9246{
76db3ba4 9247 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6a6ae23f
AJ
9248}
9249
636aa200 9250static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
6a6ae23f 9251{
76db3ba4 9252 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
9253}
9254
9255#define GEN_SPEOP_LDST(name, opc2, sh) \
99e300ef 9256static void glue(gen_, name)(DisasContext *ctx) \
6a6ae23f
AJ
9257{ \
9258 TCGv t0; \
9259 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 9260 gen_exception(ctx, POWERPC_EXCP_SPEU); \
6a6ae23f
AJ
9261 return; \
9262 } \
76db3ba4 9263 gen_set_access_type(ctx, ACCESS_INT); \
6a6ae23f
AJ
9264 t0 = tcg_temp_new(); \
9265 if (Rc(ctx->opcode)) { \
76db3ba4 9266 gen_addr_spe_imm_index(ctx, t0, sh); \
6a6ae23f 9267 } else { \
76db3ba4 9268 gen_addr_reg_index(ctx, t0); \
6a6ae23f
AJ
9269 } \
9270 gen_op_##name(ctx, t0); \
9271 tcg_temp_free(t0); \
9272}
9273
9274GEN_SPEOP_LDST(evldd, 0x00, 3);
9275GEN_SPEOP_LDST(evldw, 0x01, 3);
9276GEN_SPEOP_LDST(evldh, 0x02, 3);
9277GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
9278GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
9279GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
9280GEN_SPEOP_LDST(evlwhe, 0x08, 2);
9281GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
9282GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
9283GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
9284GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
9285
9286GEN_SPEOP_LDST(evstdd, 0x10, 3);
9287GEN_SPEOP_LDST(evstdw, 0x11, 3);
9288GEN_SPEOP_LDST(evstdh, 0x12, 3);
9289GEN_SPEOP_LDST(evstwhe, 0x18, 2);
9290GEN_SPEOP_LDST(evstwho, 0x1A, 2);
9291GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
9292GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
0487d6a8
JM
9293
9294/* Multiply and add - TODO */
9295#if 0
70560da7
FC
9296GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);//
9297GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9298GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9299GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9300GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9301GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9302GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9303GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9304GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9305GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9306GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE);
9307GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9308
9309GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9310GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9311GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9312GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9313GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9314GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9315GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9316GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
9317GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, 0x00000000, PPC_SPE);
9318GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9319GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9320GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9321
9322GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9323GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9324GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9325GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
9326GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, 0x00000000, PPC_SPE);
9327
9328GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9329GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9330GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9331GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9332GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9333GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9334GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9335GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9336GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9337GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9338GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, 0x00000000, PPC_SPE);
9339GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9340
9341GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, 0x00000000, PPC_SPE);
9342GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, 0x00000000, PPC_SPE);
9343GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9344GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9345
9346GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9347GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9348GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9349GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9350GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9351GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9352GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9353GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9354GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9355GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9356GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, 0x00000000, PPC_SPE);
9357GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9358
9359GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, 0x00000000, PPC_SPE);
9360GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, 0x00000000, PPC_SPE);
9361GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
9362GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, 0x00000000, PPC_SPE);
9363GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
0487d6a8
JM
9364#endif
9365
9366/*** SPE floating-point extension ***/
1c97856d 9367#define GEN_SPEFPUOP_CONV_32_32(name) \
636aa200 9368static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
9369{ \
9370 TCGv_i32 t0 = tcg_temp_new_i32(); \
9371 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
13b6a455
AG
9372 gen_helper_##name(t0, cpu_env, t0); \
9373 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
1c97856d 9374 tcg_temp_free_i32(t0); \
57951c27 9375}
1c97856d 9376#define GEN_SPEFPUOP_CONV_32_64(name) \
636aa200 9377static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
9378{ \
9379 TCGv_i64 t0 = tcg_temp_new_i64(); \
13b6a455 9380 TCGv_i32 t1 = tcg_temp_new_i32(); \
1c97856d 9381 gen_load_gpr64(t0, rB(ctx->opcode)); \
13b6a455
AG
9382 gen_helper_##name(t1, cpu_env, t0); \
9383 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1); \
1c97856d 9384 tcg_temp_free_i64(t0); \
13b6a455 9385 tcg_temp_free_i32(t1); \
1c97856d
AJ
9386}
9387#define GEN_SPEFPUOP_CONV_64_32(name) \
636aa200 9388static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
9389{ \
9390 TCGv_i64 t0 = tcg_temp_new_i64(); \
13b6a455
AG
9391 TCGv_i32 t1 = tcg_temp_new_i32(); \
9392 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
9393 gen_helper_##name(t0, cpu_env, t1); \
1c97856d
AJ
9394 gen_store_gpr64(rD(ctx->opcode), t0); \
9395 tcg_temp_free_i64(t0); \
13b6a455 9396 tcg_temp_free_i32(t1); \
1c97856d
AJ
9397}
9398#define GEN_SPEFPUOP_CONV_64_64(name) \
636aa200 9399static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
9400{ \
9401 TCGv_i64 t0 = tcg_temp_new_i64(); \
9402 gen_load_gpr64(t0, rB(ctx->opcode)); \
8e703949 9403 gen_helper_##name(t0, cpu_env, t0); \
1c97856d
AJ
9404 gen_store_gpr64(rD(ctx->opcode), t0); \
9405 tcg_temp_free_i64(t0); \
9406}
9407#define GEN_SPEFPUOP_ARITH2_32_32(name) \
636aa200 9408static inline void gen_##name(DisasContext *ctx) \
1c97856d 9409{ \
13b6a455 9410 TCGv_i32 t0, t1; \
1c97856d 9411 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 9412 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
9413 return; \
9414 } \
13b6a455
AG
9415 t0 = tcg_temp_new_i32(); \
9416 t1 = tcg_temp_new_i32(); \
9417 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
9418 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
9419 gen_helper_##name(t0, cpu_env, t0, t1); \
9420 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
9421 \
9422 tcg_temp_free_i32(t0); \
9423 tcg_temp_free_i32(t1); \
1c97856d
AJ
9424}
9425#define GEN_SPEFPUOP_ARITH2_64_64(name) \
636aa200 9426static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
9427{ \
9428 TCGv_i64 t0, t1; \
9429 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 9430 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
9431 return; \
9432 } \
9433 t0 = tcg_temp_new_i64(); \
9434 t1 = tcg_temp_new_i64(); \
9435 gen_load_gpr64(t0, rA(ctx->opcode)); \
9436 gen_load_gpr64(t1, rB(ctx->opcode)); \
8e703949 9437 gen_helper_##name(t0, cpu_env, t0, t1); \
1c97856d
AJ
9438 gen_store_gpr64(rD(ctx->opcode), t0); \
9439 tcg_temp_free_i64(t0); \
9440 tcg_temp_free_i64(t1); \
9441}
9442#define GEN_SPEFPUOP_COMP_32(name) \
636aa200 9443static inline void gen_##name(DisasContext *ctx) \
1c97856d 9444{ \
13b6a455 9445 TCGv_i32 t0, t1; \
1c97856d 9446 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 9447 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
9448 return; \
9449 } \
13b6a455
AG
9450 t0 = tcg_temp_new_i32(); \
9451 t1 = tcg_temp_new_i32(); \
9452 \
9453 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
9454 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
9455 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
9456 \
9457 tcg_temp_free_i32(t0); \
9458 tcg_temp_free_i32(t1); \
1c97856d
AJ
9459}
9460#define GEN_SPEFPUOP_COMP_64(name) \
636aa200 9461static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
9462{ \
9463 TCGv_i64 t0, t1; \
9464 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 9465 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
9466 return; \
9467 } \
9468 t0 = tcg_temp_new_i64(); \
9469 t1 = tcg_temp_new_i64(); \
9470 gen_load_gpr64(t0, rA(ctx->opcode)); \
9471 gen_load_gpr64(t1, rB(ctx->opcode)); \
8e703949 9472 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
1c97856d
AJ
9473 tcg_temp_free_i64(t0); \
9474 tcg_temp_free_i64(t1); \
9475}
57951c27 9476
0487d6a8
JM
9477/* Single precision floating-point vectors operations */
9478/* Arithmetic */
1c97856d
AJ
9479GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
9480GEN_SPEFPUOP_ARITH2_64_64(evfssub);
9481GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
9482GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
636aa200 9483static inline void gen_evfsabs(DisasContext *ctx)
1c97856d
AJ
9484{
9485 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 9486 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
9487 return;
9488 }
13b6a455
AG
9489 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
9490 ~0x80000000);
9491 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9492 ~0x80000000);
1c97856d 9493}
636aa200 9494static inline void gen_evfsnabs(DisasContext *ctx)
1c97856d
AJ
9495{
9496 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 9497 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
9498 return;
9499 }
13b6a455
AG
9500 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
9501 0x80000000);
9502 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9503 0x80000000);
1c97856d 9504}
636aa200 9505static inline void gen_evfsneg(DisasContext *ctx)
1c97856d
AJ
9506{
9507 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 9508 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
9509 return;
9510 }
13b6a455
AG
9511 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
9512 0x80000000);
9513 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9514 0x80000000);
1c97856d
AJ
9515}
9516
0487d6a8 9517/* Conversion */
1c97856d
AJ
9518GEN_SPEFPUOP_CONV_64_64(evfscfui);
9519GEN_SPEFPUOP_CONV_64_64(evfscfsi);
9520GEN_SPEFPUOP_CONV_64_64(evfscfuf);
9521GEN_SPEFPUOP_CONV_64_64(evfscfsf);
9522GEN_SPEFPUOP_CONV_64_64(evfsctui);
9523GEN_SPEFPUOP_CONV_64_64(evfsctsi);
9524GEN_SPEFPUOP_CONV_64_64(evfsctuf);
9525GEN_SPEFPUOP_CONV_64_64(evfsctsf);
9526GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
9527GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
9528
0487d6a8 9529/* Comparison */
1c97856d
AJ
9530GEN_SPEFPUOP_COMP_64(evfscmpgt);
9531GEN_SPEFPUOP_COMP_64(evfscmplt);
9532GEN_SPEFPUOP_COMP_64(evfscmpeq);
9533GEN_SPEFPUOP_COMP_64(evfststgt);
9534GEN_SPEFPUOP_COMP_64(evfststlt);
9535GEN_SPEFPUOP_COMP_64(evfststeq);
0487d6a8
JM
9536
9537/* Opcodes definitions */
70560da7
FC
9538GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9539GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
9540GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9541GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9542GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9543GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9544GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9545GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9546GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9547GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9548GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9549GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9550GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9551GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
0487d6a8
JM
9552
9553/* Single precision floating-point operations */
9554/* Arithmetic */
1c97856d
AJ
9555GEN_SPEFPUOP_ARITH2_32_32(efsadd);
9556GEN_SPEFPUOP_ARITH2_32_32(efssub);
9557GEN_SPEFPUOP_ARITH2_32_32(efsmul);
9558GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
636aa200 9559static inline void gen_efsabs(DisasContext *ctx)
1c97856d
AJ
9560{
9561 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 9562 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
9563 return;
9564 }
6d5c34fa 9565 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
1c97856d 9566}
636aa200 9567static inline void gen_efsnabs(DisasContext *ctx)
1c97856d
AJ
9568{
9569 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 9570 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
9571 return;
9572 }
6d5c34fa 9573 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1c97856d 9574}
636aa200 9575static inline void gen_efsneg(DisasContext *ctx)
1c97856d
AJ
9576{
9577 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 9578 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
9579 return;
9580 }
6d5c34fa 9581 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
9582}
9583
0487d6a8 9584/* Conversion */
1c97856d
AJ
9585GEN_SPEFPUOP_CONV_32_32(efscfui);
9586GEN_SPEFPUOP_CONV_32_32(efscfsi);
9587GEN_SPEFPUOP_CONV_32_32(efscfuf);
9588GEN_SPEFPUOP_CONV_32_32(efscfsf);
9589GEN_SPEFPUOP_CONV_32_32(efsctui);
9590GEN_SPEFPUOP_CONV_32_32(efsctsi);
9591GEN_SPEFPUOP_CONV_32_32(efsctuf);
9592GEN_SPEFPUOP_CONV_32_32(efsctsf);
9593GEN_SPEFPUOP_CONV_32_32(efsctuiz);
9594GEN_SPEFPUOP_CONV_32_32(efsctsiz);
9595GEN_SPEFPUOP_CONV_32_64(efscfd);
9596
0487d6a8 9597/* Comparison */
1c97856d
AJ
9598GEN_SPEFPUOP_COMP_32(efscmpgt);
9599GEN_SPEFPUOP_COMP_32(efscmplt);
9600GEN_SPEFPUOP_COMP_32(efscmpeq);
9601GEN_SPEFPUOP_COMP_32(efststgt);
9602GEN_SPEFPUOP_COMP_32(efststlt);
9603GEN_SPEFPUOP_COMP_32(efststeq);
0487d6a8
JM
9604
9605/* Opcodes definitions */
70560da7
FC
9606GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9607GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
9608GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9609GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
9610GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9611GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE); //
9612GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9613GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9614GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9615GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
9616GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9617GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
9618GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
9619GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
0487d6a8
JM
9620
9621/* Double precision floating-point operations */
9622/* Arithmetic */
1c97856d
AJ
9623GEN_SPEFPUOP_ARITH2_64_64(efdadd);
9624GEN_SPEFPUOP_ARITH2_64_64(efdsub);
9625GEN_SPEFPUOP_ARITH2_64_64(efdmul);
9626GEN_SPEFPUOP_ARITH2_64_64(efddiv);
636aa200 9627static inline void gen_efdabs(DisasContext *ctx)
1c97856d
AJ
9628{
9629 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 9630 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
9631 return;
9632 }
6d5c34fa 9633 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
13b6a455
AG
9634 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9635 ~0x80000000);
1c97856d 9636}
636aa200 9637static inline void gen_efdnabs(DisasContext *ctx)
1c97856d
AJ
9638{
9639 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 9640 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
9641 return;
9642 }
6d5c34fa 9643 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
13b6a455
AG
9644 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9645 0x80000000);
1c97856d 9646}
636aa200 9647static inline void gen_efdneg(DisasContext *ctx)
1c97856d
AJ
9648{
9649 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 9650 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
9651 return;
9652 }
6d5c34fa 9653 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
13b6a455
AG
9654 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)],
9655 0x80000000);
1c97856d
AJ
9656}
9657
0487d6a8 9658/* Conversion */
1c97856d
AJ
9659GEN_SPEFPUOP_CONV_64_32(efdcfui);
9660GEN_SPEFPUOP_CONV_64_32(efdcfsi);
9661GEN_SPEFPUOP_CONV_64_32(efdcfuf);
9662GEN_SPEFPUOP_CONV_64_32(efdcfsf);
9663GEN_SPEFPUOP_CONV_32_64(efdctui);
9664GEN_SPEFPUOP_CONV_32_64(efdctsi);
9665GEN_SPEFPUOP_CONV_32_64(efdctuf);
9666GEN_SPEFPUOP_CONV_32_64(efdctsf);
9667GEN_SPEFPUOP_CONV_32_64(efdctuiz);
9668GEN_SPEFPUOP_CONV_32_64(efdctsiz);
9669GEN_SPEFPUOP_CONV_64_32(efdcfs);
9670GEN_SPEFPUOP_CONV_64_64(efdcfuid);
9671GEN_SPEFPUOP_CONV_64_64(efdcfsid);
9672GEN_SPEFPUOP_CONV_64_64(efdctuidz);
9673GEN_SPEFPUOP_CONV_64_64(efdctsidz);
0487d6a8 9674
0487d6a8 9675/* Comparison */
1c97856d
AJ
9676GEN_SPEFPUOP_COMP_64(efdcmpgt);
9677GEN_SPEFPUOP_COMP_64(efdcmplt);
9678GEN_SPEFPUOP_COMP_64(efdcmpeq);
9679GEN_SPEFPUOP_COMP_64(efdtstgt);
9680GEN_SPEFPUOP_COMP_64(efdtstlt);
9681GEN_SPEFPUOP_COMP_64(efdtsteq);
0487d6a8
JM
9682
9683/* Opcodes definitions */
70560da7
FC
9684GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
9685GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9686GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE); //
9687GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9688GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
9689GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9690GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
9691GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE); //
9692GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9693GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9694GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9695GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
9696GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9697GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
9698GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
9699GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
0487d6a8 9700
0ff93d11
TM
9701static void gen_tbegin(DisasContext *ctx)
9702{
9703 if (unlikely(!ctx->tm_enabled)) {
9704 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
9705 return;
9706 }
9707 gen_helper_tbegin(cpu_env);
9708}
9709
56a84615
TM
9710#define GEN_TM_NOOP(name) \
9711static inline void gen_##name(DisasContext *ctx) \
9712{ \
9713 if (unlikely(!ctx->tm_enabled)) { \
9714 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
9715 return; \
9716 } \
9717 /* Because tbegin always fails in QEMU, these user \
9718 * space instructions all have a simple implementation: \
9719 * \
9720 * CR[0] = 0b0 || MSR[TS] || 0b0 \
9721 * = 0b0 || 0b00 || 0b0 \
9722 */ \
9723 tcg_gen_movi_i32(cpu_crf[0], 0); \
9724}
9725
9726GEN_TM_NOOP(tend);
9727GEN_TM_NOOP(tabort);
9728GEN_TM_NOOP(tabortwc);
9729GEN_TM_NOOP(tabortwci);
9730GEN_TM_NOOP(tabortdc);
9731GEN_TM_NOOP(tabortdci);
9732GEN_TM_NOOP(tsr);
9733
aeedd582
TM
9734static void gen_tcheck(DisasContext *ctx)
9735{
9736 if (unlikely(!ctx->tm_enabled)) {
9737 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
9738 return;
9739 }
9740 /* Because tbegin always fails, the tcheck implementation
9741 * is simple:
9742 *
9743 * CR[CRF] = TDOOMED || MSR[TS] || 0b0
9744 * = 0b1 || 0b00 || 0b0
9745 */
9746 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0x8);
9747}
9748
f83c2378
TM
9749#if defined(CONFIG_USER_ONLY)
9750#define GEN_TM_PRIV_NOOP(name) \
9751static inline void gen_##name(DisasContext *ctx) \
9752{ \
9b2fadda 9753 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); \
f83c2378
TM
9754}
9755
9756#else
9757
9758#define GEN_TM_PRIV_NOOP(name) \
9759static inline void gen_##name(DisasContext *ctx) \
9760{ \
9b2fadda 9761 CHK_SV; \
f83c2378
TM
9762 if (unlikely(!ctx->tm_enabled)) { \
9763 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
9764 return; \
9765 } \
9766 /* Because tbegin always fails, the implementation is \
9767 * simple: \
9768 * \
9769 * CR[0] = 0b0 || MSR[TS] || 0b0 \
9770 * = 0b0 || 0b00 | 0b0 \
9771 */ \
9772 tcg_gen_movi_i32(cpu_crf[0], 0); \
9773}
9774
9775#endif
9776
9777GEN_TM_PRIV_NOOP(treclaim);
9778GEN_TM_PRIV_NOOP(trechkpt);
9779
c227f099 9780static opcode_t opcodes[] = {
5c55ff99
BS
9781GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
9782GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
9783GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
9784GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
9785GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
fcfda20f 9786GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
5c55ff99
BS
9787GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
9788GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9789GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9790GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9791GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9792GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
9793GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
9794GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
9795GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
9796GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9797#if defined(TARGET_PPC64)
9798GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
9799#endif
9800GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
9801GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
9802GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9803GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9804GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9805GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
9806GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
9807GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
9808GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9809GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9810GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9811GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6ab39b1b 9812GEN_HANDLER(popcntb, 0x1F, 0x1A, 0x03, 0x0000F801, PPC_POPCNTB),
eaabeef2 9813GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
725bcec2 9814GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
5c55ff99 9815#if defined(TARGET_PPC64)
eaabeef2 9816GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
5c55ff99 9817GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
725bcec2 9818GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
86ba37ed 9819GEN_HANDLER_E(bpermd, 0x1F, 0x1C, 0x07, 0x00000001, PPC_NONE, PPC2_PERM_ISA206),
5c55ff99
BS
9820#endif
9821GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9822GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9823GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9824GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
9825GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
9826GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
9827GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
9828#if defined(TARGET_PPC64)
9829GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
9830GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
9831GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
9832GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
9833GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
9834#endif
9835GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
9836GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
9837GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
9838GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
9839GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
bf45a2e6 9840GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT),
5c55ff99 9841GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
bf45a2e6
AJ
9842GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT),
9843GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT),
f0332888 9844GEN_HANDLER_E(fcpsgn, 0x3F, 0x08, 0x00, 0x00000000, PPC_NONE, PPC2_ISA205),
097ec5d8
TM
9845GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x00000001, PPC_NONE, PPC2_VSX207),
9846GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x00000001, PPC_NONE, PPC2_VSX207),
5c55ff99
BS
9847GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
9848GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
9849GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
9850GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
7d08d856
AJ
9851GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00000000, PPC_FLOAT),
9852GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006e0800, PPC_FLOAT),
5c55ff99
BS
9853#if defined(TARGET_PPC64)
9854GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
9855GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
9856GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
9857#endif
9858GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9859GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
9860GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
9861GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
9862GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
9863GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
9864GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
9865GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
5c77a786
TM
9866GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9867GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
f844c817 9868GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
587c51f7
TM
9869GEN_HANDLER_E(stbcx_, 0x1F, 0x16, 0x15, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
9870GEN_HANDLER_E(sthcx_, 0x1F, 0x16, 0x16, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
5c55ff99
BS
9871GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
9872#if defined(TARGET_PPC64)
f844c817 9873GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
9c294d5a 9874GEN_HANDLER_E(lqarx, 0x1F, 0x14, 0x08, 0, PPC_NONE, PPC2_LSQ_ISA207),
5c55ff99 9875GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
27b95bfe 9876GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207),
5c55ff99
BS
9877#endif
9878GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
9879GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
9880GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
9881GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
9882GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
9883GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
52a4984d 9884GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0, PPC_NONE, PPC2_BCTAR_ISA207),
5c55ff99
BS
9885GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
9886GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
9887#if defined(TARGET_PPC64)
9888GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
9889GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
9890#endif
9891GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
9892GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
9893GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
9894#if defined(TARGET_PPC64)
9895GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
9896GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
9897#endif
9898GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
9899GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
9900GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
9901GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
9902GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
9903GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
9904#if defined(TARGET_PPC64)
9905GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
9906#endif
5e31867f 9907GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001EF801, PPC_MISC),
4248b336 9908GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000000, PPC_MISC),
5c55ff99
BS
9909GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
9910GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
9911GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
3f34cf91
CLG
9912GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE),
9913GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
4d09d529 9914GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
8e33944f 9915GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
5c55ff99
BS
9916GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
9917GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
9918GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
9919GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
9920GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
9921GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
9922GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
9923GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
9924GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
9925#if defined(TARGET_PPC64)
9926GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
9927GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
9928 PPC_SEGMENT_64B),
9929GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
9930GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
9931 PPC_SEGMENT_64B),
efdef95f
DG
9932GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
9933GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
9934GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
c76c22d5 9935GEN_HANDLER2(slbfee_, "slbfee.", 0x1F, 0x13, 0x1E, 0x001F0000, PPC_SEGMENT_64B),
5c55ff99
BS
9936#endif
9937GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
f9ef0527
BH
9938/* XXX Those instructions will need to be handled differently for
9939 * different ISA versions */
9940GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x001F0001, PPC_MEM_TLBIE),
9941GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x001F0001, PPC_MEM_TLBIE),
5c55ff99
BS
9942GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
9943#if defined(TARGET_PPC64)
2f9254d9 9944GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x031FFC01, PPC_SLBI),
5c55ff99
BS
9945GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
9946#endif
9947GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
9948GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
9949GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
9950GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
9951GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
9952GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
9953GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
9954GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
9955GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
9956GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
9957GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
9958GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
9959GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
9960GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
9961GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
9962GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
9963GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
9964GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
9965GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
9966GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
9967GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
9968GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
9969GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
9970GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
9971GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
9972GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
9973GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
9974GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
9975GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
9976GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
9977GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
9978GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
9979GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
9980GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
9981GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
9982GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
9983GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
9984GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
9985GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
9986GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
9987GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
9988GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
9989GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
9990GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
9991GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
9992GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
9993GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
9994GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
9995GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
9996GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
9997GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
9998GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
9999GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
10000GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10001GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
10002GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
10003GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
10004GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
10005GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
10006GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
10007GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
10008GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
10009GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
10010GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
10011GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
10012GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
10013GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
10014GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
10015GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
10016GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
10017GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
01662f3e 10018GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
5c55ff99
BS
10019GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
10020GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
10021GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
10022GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
10023GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
10024GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
10025GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
10026GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
01662f3e
AG
10027GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
10028 PPC_NONE, PPC2_BOOKE206),
10029GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
10030 PPC_NONE, PPC2_BOOKE206),
10031GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
10032 PPC_NONE, PPC2_BOOKE206),
10033GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
10034 PPC_NONE, PPC2_BOOKE206),
6d3db821
AG
10035GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
10036 PPC_NONE, PPC2_BOOKE206),
d5d11a39
AG
10037GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
10038 PPC_NONE, PPC2_PRCNTL),
9e0b5cb1
AG
10039GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
10040 PPC_NONE, PPC2_PRCNTL),
5c55ff99 10041GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
fbe73008 10042GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
5c55ff99 10043GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
01662f3e
AG
10044GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
10045 PPC_BOOKE, PPC2_BOOKE206),
dcb2b9e1 10046GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
01662f3e
AG
10047GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
10048 PPC_BOOKE, PPC2_BOOKE206),
5c55ff99
BS
10049GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
10050GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
10051GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
10052GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
5c55ff99
BS
10053GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
10054GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
10055GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
10056GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
10057GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),
10058
10059#undef GEN_INT_ARITH_ADD
10060#undef GEN_INT_ARITH_ADD_CONST
10061#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
10062GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
10063#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
10064 add_ca, compute_ca, compute_ov) \
10065GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
10066GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
10067GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
10068GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
10069GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
10070GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
10071GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
10072GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
10073GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
10074GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
10075GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
10076
10077#undef GEN_INT_ARITH_DIVW
10078#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
10079GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
10080GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
10081GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
10082GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
10083GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
a98eb9e9
TM
10084GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10085GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6a4fda33
TM
10086GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10087GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
5c55ff99
BS
10088
10089#if defined(TARGET_PPC64)
10090#undef GEN_INT_ARITH_DIVD
10091#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
10092GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
10093GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
10094GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
10095GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
10096GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
10097
98d1eb27
TM
10098GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
10099GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
e44259b6
TM
10100GEN_HANDLER_E(divde, 0x1F, 0x09, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
10101GEN_HANDLER_E(divdeo, 0x1F, 0x09, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
98d1eb27 10102
5c55ff99
BS
10103#undef GEN_INT_ARITH_MUL_HELPER
10104#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
10105GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
10106GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
10107GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
10108GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
10109#endif
10110
10111#undef GEN_INT_ARITH_SUBF
10112#undef GEN_INT_ARITH_SUBF_CONST
10113#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
10114GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
10115#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
10116 add_ca, compute_ca, compute_ov) \
10117GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
10118GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
10119GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
10120GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
10121GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
10122GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
10123GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
10124GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
10125GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
10126GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
10127GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
10128
10129#undef GEN_LOGICAL1
10130#undef GEN_LOGICAL2
10131#define GEN_LOGICAL2(name, tcg_op, opc, type) \
10132GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
10133#define GEN_LOGICAL1(name, tcg_op, opc, type) \
10134GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
10135GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
10136GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
10137GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
10138GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
10139GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
10140GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
10141GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
10142GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
10143#if defined(TARGET_PPC64)
10144GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
10145#endif
10146
10147#if defined(TARGET_PPC64)
10148#undef GEN_PPC64_R2
10149#undef GEN_PPC64_R4
10150#define GEN_PPC64_R2(name, opc1, opc2) \
10151GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
10152GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
10153 PPC_64B)
10154#define GEN_PPC64_R4(name, opc1, opc2) \
10155GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
10156GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
10157 PPC_64B), \
10158GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
10159 PPC_64B), \
10160GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
10161 PPC_64B)
10162GEN_PPC64_R4(rldicl, 0x1E, 0x00),
10163GEN_PPC64_R4(rldicr, 0x1E, 0x02),
10164GEN_PPC64_R4(rldic, 0x1E, 0x04),
10165GEN_PPC64_R2(rldcl, 0x1E, 0x08),
10166GEN_PPC64_R2(rldcr, 0x1E, 0x09),
10167GEN_PPC64_R4(rldimi, 0x1E, 0x06),
10168#endif
10169
10170#undef _GEN_FLOAT_ACB
10171#undef GEN_FLOAT_ACB
10172#undef _GEN_FLOAT_AB
10173#undef GEN_FLOAT_AB
10174#undef _GEN_FLOAT_AC
10175#undef GEN_FLOAT_AC
10176#undef GEN_FLOAT_B
10177#undef GEN_FLOAT_BS
10178#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
10179GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
10180#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
10181_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type), \
10182_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type)
10183#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
10184GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
10185#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
10186_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
10187_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
10188#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
10189GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
10190#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
10191_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
10192_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
10193#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
10194GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
10195#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
10196GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)
10197
10198GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
10199GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
10200GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
10201GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
10202GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
10203GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
10204_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
10205GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
10206GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
10207GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
10208GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
10209GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
da29cb7b 10210GEN_HANDLER_E(ftdiv, 0x3F, 0x00, 0x04, 1, PPC_NONE, PPC2_FP_TST_ISA206),
6d41d146 10211GEN_HANDLER_E(ftsqrt, 0x3F, 0x00, 0x05, 1, PPC_NONE, PPC2_FP_TST_ISA206),
5c55ff99 10212GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
fab7fe42 10213GEN_HANDLER_E(fctiwu, 0x3F, 0x0E, 0x04, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
5c55ff99 10214GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
fab7fe42 10215GEN_HANDLER_E(fctiwuz, 0x3F, 0x0F, 0x04, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
5c55ff99 10216GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
4171853c 10217GEN_HANDLER_E(fcfid, 0x3F, 0x0E, 0x1A, 0x001F0000, PPC_NONE, PPC2_FP_CVT_S64),
28288b48
TM
10218GEN_HANDLER_E(fcfids, 0x3B, 0x0E, 0x1A, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10219GEN_HANDLER_E(fcfidu, 0x3F, 0x0E, 0x1E, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
10220GEN_HANDLER_E(fcfidus, 0x3B, 0x0E, 0x1E, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
4171853c 10221GEN_HANDLER_E(fctid, 0x3F, 0x0E, 0x19, 0x001F0000, PPC_NONE, PPC2_FP_CVT_S64),
fab7fe42 10222GEN_HANDLER_E(fctidu, 0x3F, 0x0E, 0x1D, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
4171853c 10223GEN_HANDLER_E(fctidz, 0x3F, 0x0F, 0x19, 0x001F0000, PPC_NONE, PPC2_FP_CVT_S64),
fab7fe42 10224GEN_HANDLER_E(fctiduz, 0x3F, 0x0F, 0x1D, 0, PPC_NONE, PPC2_FP_CVT_ISA206),
5c55ff99
BS
10225GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
10226GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
10227GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
10228GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
5c55ff99
BS
10229
10230#undef GEN_LD
10231#undef GEN_LDU
10232#undef GEN_LDUX
cd6e9320 10233#undef GEN_LDX_E
5c55ff99
BS
10234#undef GEN_LDS
10235#define GEN_LD(name, ldop, opc, type) \
10236GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10237#define GEN_LDU(name, ldop, opc, type) \
10238GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
10239#define GEN_LDUX(name, ldop, opc2, opc3, type) \
10240GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
cd6e9320
TH
10241#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
10242GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
5c55ff99
BS
10243#define GEN_LDS(name, ldop, op, type) \
10244GEN_LD(name, ldop, op | 0x20, type) \
10245GEN_LDU(name, ldop, op | 0x21, type) \
10246GEN_LDUX(name, ldop, 0x17, op | 0x01, type) \
10247GEN_LDX(name, ldop, 0x17, op | 0x00, type)
10248
10249GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
10250GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
10251GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
10252GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
10253#if defined(TARGET_PPC64)
10254GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
10255GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
10256GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
10257GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
cd6e9320 10258GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
5c55ff99
BS
10259#endif
10260GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
10261GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
10262
10263#undef GEN_ST
10264#undef GEN_STU
10265#undef GEN_STUX
cd6e9320 10266#undef GEN_STX_E
5c55ff99
BS
10267#undef GEN_STS
10268#define GEN_ST(name, stop, opc, type) \
10269GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10270#define GEN_STU(name, stop, opc, type) \
10271GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
10272#define GEN_STUX(name, stop, opc2, opc3, type) \
10273GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
cd6e9320
TH
10274#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
10275GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
5c55ff99
BS
10276#define GEN_STS(name, stop, op, type) \
10277GEN_ST(name, stop, op | 0x20, type) \
10278GEN_STU(name, stop, op | 0x21, type) \
10279GEN_STUX(name, stop, 0x17, op | 0x01, type) \
10280GEN_STX(name, stop, 0x17, op | 0x00, type)
10281
10282GEN_STS(stb, st8, 0x06, PPC_INTEGER)
10283GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
10284GEN_STS(stw, st32, 0x04, PPC_INTEGER)
10285#if defined(TARGET_PPC64)
10286GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
10287GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
cd6e9320 10288GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
5c55ff99
BS
10289#endif
10290GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
10291GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
10292
10293#undef GEN_LDF
10294#undef GEN_LDUF
10295#undef GEN_LDUXF
10296#undef GEN_LDXF
10297#undef GEN_LDFS
10298#define GEN_LDF(name, ldop, opc, type) \
10299GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10300#define GEN_LDUF(name, ldop, opc, type) \
10301GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
10302#define GEN_LDUXF(name, ldop, opc, type) \
10303GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
10304#define GEN_LDXF(name, ldop, opc2, opc3, type) \
10305GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
10306#define GEN_LDFS(name, ldop, op, type) \
10307GEN_LDF(name, ldop, op | 0x20, type) \
10308GEN_LDUF(name, ldop, op | 0x21, type) \
10309GEN_LDUXF(name, ldop, op | 0x01, type) \
10310GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
10311
10312GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
10313GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
199f830d 10314GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
66c3e328 10315GEN_HANDLER_E(lfiwzx, 0x1f, 0x17, 0x1b, 0x1, PPC_NONE, PPC2_FP_CVT_ISA206),
05050ee8
AJ
10316GEN_HANDLER_E(lfdp, 0x39, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
10317GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205),
5c55ff99
BS
10318
10319#undef GEN_STF
10320#undef GEN_STUF
10321#undef GEN_STUXF
10322#undef GEN_STXF
10323#undef GEN_STFS
10324#define GEN_STF(name, stop, opc, type) \
10325GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
10326#define GEN_STUF(name, stop, opc, type) \
10327GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
10328#define GEN_STUXF(name, stop, opc, type) \
10329GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
10330#define GEN_STXF(name, stop, opc2, opc3, type) \
10331GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
10332#define GEN_STFS(name, stop, op, type) \
10333GEN_STF(name, stop, op | 0x20, type) \
10334GEN_STUF(name, stop, op | 0x21, type) \
10335GEN_STUXF(name, stop, op | 0x01, type) \
10336GEN_STXF(name, stop, 0x17, op | 0x00, type)
10337
10338GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
10339GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
10340GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
44bc0c4d
AJ
10341GEN_HANDLER_E(stfdp, 0x3D, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
10342GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205),
5c55ff99
BS
10343
10344#undef GEN_CRLOGIC
10345#define GEN_CRLOGIC(name, tcg_op, opc) \
10346GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
10347GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
10348GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
10349GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
10350GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
10351GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
10352GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
10353GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
10354GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
10355
10356#undef GEN_MAC_HANDLER
10357#define GEN_MAC_HANDLER(name, opc2, opc3) \
10358GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
10359GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
10360GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
10361GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
10362GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
10363GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
10364GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
10365GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
10366GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
10367GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
10368GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
10369GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
10370GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
10371GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
10372GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
10373GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
10374GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
10375GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
10376GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
10377GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
10378GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
10379GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
10380GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
10381GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
10382GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
10383GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
10384GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
10385GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
10386GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
10387GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
10388GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
10389GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
10390GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
10391GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
10392GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
10393GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
10394GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
10395GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
10396GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
10397GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
10398GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
10399GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
10400GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
10401
10402#undef GEN_VR_LDX
10403#undef GEN_VR_STX
10404#undef GEN_VR_LVE
10405#undef GEN_VR_STVE
10406#define GEN_VR_LDX(name, opc2, opc3) \
10407GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10408#define GEN_VR_STX(name, opc2, opc3) \
10409GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10410#define GEN_VR_LVE(name, opc2, opc3) \
10411 GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10412#define GEN_VR_STVE(name, opc2, opc3) \
10413 GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
10414GEN_VR_LDX(lvx, 0x07, 0x03),
10415GEN_VR_LDX(lvxl, 0x07, 0x0B),
10416GEN_VR_LVE(bx, 0x07, 0x00),
10417GEN_VR_LVE(hx, 0x07, 0x01),
10418GEN_VR_LVE(wx, 0x07, 0x02),
10419GEN_VR_STX(svx, 0x07, 0x07),
10420GEN_VR_STX(svxl, 0x07, 0x0F),
10421GEN_VR_STVE(bx, 0x07, 0x04),
10422GEN_VR_STVE(hx, 0x07, 0x05),
10423GEN_VR_STVE(wx, 0x07, 0x06),
10424
10425#undef GEN_VX_LOGICAL
10426#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
10427GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
111c5f54
TM
10428
10429#undef GEN_VX_LOGICAL_207
10430#define GEN_VX_LOGICAL_207(name, tcg_op, opc2, opc3) \
10431GEN_HANDLER_E(name, 0x04, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ALTIVEC_207)
10432
5c55ff99
BS
10433GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
10434GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
10435GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
10436GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
10437GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),
111c5f54
TM
10438GEN_VX_LOGICAL_207(veqv, tcg_gen_eqv_i64, 2, 26),
10439GEN_VX_LOGICAL_207(vnand, tcg_gen_nand_i64, 2, 22),
10440GEN_VX_LOGICAL_207(vorc, tcg_gen_orc_i64, 2, 21),
5c55ff99
BS
10441
10442#undef GEN_VXFORM
10443#define GEN_VXFORM(name, opc2, opc3) \
10444GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
50f5fc0c
TM
10445
10446#undef GEN_VXFORM_207
10447#define GEN_VXFORM_207(name, opc2, opc3) \
10448GEN_HANDLER_E(name, 0x04, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ALTIVEC_207)
10449
5dffff5a
TM
10450#undef GEN_VXFORM_DUAL
10451#define GEN_VXFORM_DUAL(name0, name1, opc2, opc3, type0, type1) \
10452GEN_HANDLER_E(name0##_##name1, 0x4, opc2, opc3, 0x00000000, type0, type1)
10453
a737d3eb
TM
10454#undef GEN_VXRFORM_DUAL
10455#define GEN_VXRFORM_DUAL(name0, name1, opc2, opc3, tp0, tp1) \
10456GEN_HANDLER_E(name0##_##name1, 0x4, opc2, opc3, 0x00000000, tp0, tp1), \
10457GEN_HANDLER_E(name0##_##name1, 0x4, opc2, (opc3 | 0x10), 0x00000000, tp0, tp1),
10458
5c55ff99
BS
10459GEN_VXFORM(vaddubm, 0, 0),
10460GEN_VXFORM(vadduhm, 0, 1),
10461GEN_VXFORM(vadduwm, 0, 2),
56eabc75 10462GEN_VXFORM_207(vaddudm, 0, 3),
e8f7b27b
TM
10463GEN_VXFORM_DUAL(vsububm, bcdadd, 0, 16, PPC_ALTIVEC, PPC_NONE),
10464GEN_VXFORM_DUAL(vsubuhm, bcdsub, 0, 17, PPC_ALTIVEC, PPC_NONE),
5c55ff99 10465GEN_VXFORM(vsubuwm, 0, 18),
56eabc75 10466GEN_VXFORM_207(vsubudm, 0, 19),
5c55ff99
BS
10467GEN_VXFORM(vmaxub, 1, 0),
10468GEN_VXFORM(vmaxuh, 1, 1),
10469GEN_VXFORM(vmaxuw, 1, 2),
8203e31b 10470GEN_VXFORM_207(vmaxud, 1, 3),
5c55ff99
BS
10471GEN_VXFORM(vmaxsb, 1, 4),
10472GEN_VXFORM(vmaxsh, 1, 5),
10473GEN_VXFORM(vmaxsw, 1, 6),
8203e31b 10474GEN_VXFORM_207(vmaxsd, 1, 7),
5c55ff99
BS
10475GEN_VXFORM(vminub, 1, 8),
10476GEN_VXFORM(vminuh, 1, 9),
10477GEN_VXFORM(vminuw, 1, 10),
8203e31b 10478GEN_VXFORM_207(vminud, 1, 11),
5c55ff99
BS
10479GEN_VXFORM(vminsb, 1, 12),
10480GEN_VXFORM(vminsh, 1, 13),
10481GEN_VXFORM(vminsw, 1, 14),
8203e31b 10482GEN_VXFORM_207(vminsd, 1, 15),
5c55ff99
BS
10483GEN_VXFORM(vavgub, 1, 16),
10484GEN_VXFORM(vavguh, 1, 17),
10485GEN_VXFORM(vavguw, 1, 18),
10486GEN_VXFORM(vavgsb, 1, 20),
10487GEN_VXFORM(vavgsh, 1, 21),
10488GEN_VXFORM(vavgsw, 1, 22),
10489GEN_VXFORM(vmrghb, 6, 0),
10490GEN_VXFORM(vmrghh, 6, 1),
10491GEN_VXFORM(vmrghw, 6, 2),
10492GEN_VXFORM(vmrglb, 6, 4),
10493GEN_VXFORM(vmrglh, 6, 5),
10494GEN_VXFORM(vmrglw, 6, 6),
e0ffe77f
TM
10495GEN_VXFORM_207(vmrgew, 6, 30),
10496GEN_VXFORM_207(vmrgow, 6, 26),
5c55ff99
BS
10497GEN_VXFORM(vmuloub, 4, 0),
10498GEN_VXFORM(vmulouh, 4, 1),
953f0f58 10499GEN_VXFORM_DUAL(vmulouw, vmuluwm, 4, 2, PPC_ALTIVEC, PPC_NONE),
5c55ff99
BS
10500GEN_VXFORM(vmulosb, 4, 4),
10501GEN_VXFORM(vmulosh, 4, 5),
63be0936 10502GEN_VXFORM_207(vmulosw, 4, 6),
5c55ff99
BS
10503GEN_VXFORM(vmuleub, 4, 8),
10504GEN_VXFORM(vmuleuh, 4, 9),
63be0936 10505GEN_VXFORM_207(vmuleuw, 4, 10),
5c55ff99
BS
10506GEN_VXFORM(vmulesb, 4, 12),
10507GEN_VXFORM(vmulesh, 4, 13),
63be0936 10508GEN_VXFORM_207(vmulesw, 4, 14),
5c55ff99
BS
10509GEN_VXFORM(vslb, 2, 4),
10510GEN_VXFORM(vslh, 2, 5),
10511GEN_VXFORM(vslw, 2, 6),
2fdf78e6 10512GEN_VXFORM_207(vsld, 2, 23),
5c55ff99
BS
10513GEN_VXFORM(vsrb, 2, 8),
10514GEN_VXFORM(vsrh, 2, 9),
10515GEN_VXFORM(vsrw, 2, 10),
2fdf78e6 10516GEN_VXFORM_207(vsrd, 2, 27),
5c55ff99
BS
10517GEN_VXFORM(vsrab, 2, 12),
10518GEN_VXFORM(vsrah, 2, 13),
10519GEN_VXFORM(vsraw, 2, 14),
2fdf78e6 10520GEN_VXFORM_207(vsrad, 2, 15),
5c55ff99
BS
10521GEN_VXFORM(vslo, 6, 16),
10522GEN_VXFORM(vsro, 6, 17),
10523GEN_VXFORM(vaddcuw, 0, 6),
10524GEN_VXFORM(vsubcuw, 0, 22),
10525GEN_VXFORM(vaddubs, 0, 8),
10526GEN_VXFORM(vadduhs, 0, 9),
10527GEN_VXFORM(vadduws, 0, 10),
10528GEN_VXFORM(vaddsbs, 0, 12),
10529GEN_VXFORM(vaddshs, 0, 13),
10530GEN_VXFORM(vaddsws, 0, 14),
e8f7b27b
TM
10531GEN_VXFORM_DUAL(vsububs, bcdadd, 0, 24, PPC_ALTIVEC, PPC_NONE),
10532GEN_VXFORM_DUAL(vsubuhs, bcdsub, 0, 25, PPC_ALTIVEC, PPC_NONE),
5c55ff99
BS
10533GEN_VXFORM(vsubuws, 0, 26),
10534GEN_VXFORM(vsubsbs, 0, 28),
10535GEN_VXFORM(vsubshs, 0, 29),
10536GEN_VXFORM(vsubsws, 0, 30),
b41da4eb
TM
10537GEN_VXFORM_207(vadduqm, 0, 4),
10538GEN_VXFORM_207(vaddcuq, 0, 5),
10539GEN_VXFORM_DUAL(vaddeuqm, vaddecuq, 30, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
10540GEN_VXFORM_207(vsubuqm, 0, 20),
10541GEN_VXFORM_207(vsubcuq, 0, 21),
10542GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
5c55ff99
BS
10543GEN_VXFORM(vrlb, 2, 0),
10544GEN_VXFORM(vrlh, 2, 1),
10545GEN_VXFORM(vrlw, 2, 2),
2fdf78e6 10546GEN_VXFORM_207(vrld, 2, 3),
5c55ff99
BS
10547GEN_VXFORM(vsl, 2, 7),
10548GEN_VXFORM(vsr, 2, 11),
10549GEN_VXFORM(vpkuhum, 7, 0),
10550GEN_VXFORM(vpkuwum, 7, 1),
024215b2 10551GEN_VXFORM_207(vpkudum, 7, 17),
5c55ff99
BS
10552GEN_VXFORM(vpkuhus, 7, 2),
10553GEN_VXFORM(vpkuwus, 7, 3),
024215b2 10554GEN_VXFORM_207(vpkudus, 7, 19),
5c55ff99
BS
10555GEN_VXFORM(vpkshus, 7, 4),
10556GEN_VXFORM(vpkswus, 7, 5),
024215b2 10557GEN_VXFORM_207(vpksdus, 7, 21),
5c55ff99
BS
10558GEN_VXFORM(vpkshss, 7, 6),
10559GEN_VXFORM(vpkswss, 7, 7),
024215b2 10560GEN_VXFORM_207(vpksdss, 7, 23),
5c55ff99
BS
10561GEN_VXFORM(vpkpx, 7, 12),
10562GEN_VXFORM(vsum4ubs, 4, 24),
10563GEN_VXFORM(vsum4sbs, 4, 28),
10564GEN_VXFORM(vsum4shs, 4, 25),
10565GEN_VXFORM(vsum2sws, 4, 26),
10566GEN_VXFORM(vsumsws, 4, 30),
10567GEN_VXFORM(vaddfp, 5, 0),
10568GEN_VXFORM(vsubfp, 5, 1),
10569GEN_VXFORM(vmaxfp, 5, 16),
10570GEN_VXFORM(vminfp, 5, 17),
10571
10572#undef GEN_VXRFORM1
10573#undef GEN_VXRFORM
10574#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
10575 GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
10576#define GEN_VXRFORM(name, opc2, opc3) \
10577 GEN_VXRFORM1(name, name, #name, opc2, opc3) \
10578 GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
10579GEN_VXRFORM(vcmpequb, 3, 0)
10580GEN_VXRFORM(vcmpequh, 3, 1)
10581GEN_VXRFORM(vcmpequw, 3, 2)
10582GEN_VXRFORM(vcmpgtsb, 3, 12)
10583GEN_VXRFORM(vcmpgtsh, 3, 13)
10584GEN_VXRFORM(vcmpgtsw, 3, 14)
10585GEN_VXRFORM(vcmpgtub, 3, 8)
10586GEN_VXRFORM(vcmpgtuh, 3, 9)
10587GEN_VXRFORM(vcmpgtuw, 3, 10)
6f3dab41 10588GEN_VXRFORM_DUAL(vcmpeqfp, vcmpequd, 3, 3, PPC_ALTIVEC, PPC_NONE)
5c55ff99 10589GEN_VXRFORM(vcmpgefp, 3, 7)
6f3dab41
TM
10590GEN_VXRFORM_DUAL(vcmpgtfp, vcmpgtud, 3, 11, PPC_ALTIVEC, PPC_NONE)
10591GEN_VXRFORM_DUAL(vcmpbfp, vcmpgtsd, 3, 15, PPC_ALTIVEC, PPC_NONE)
5c55ff99
BS
10592
10593#undef GEN_VXFORM_SIMM
10594#define GEN_VXFORM_SIMM(name, opc2, opc3) \
10595 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10596GEN_VXFORM_SIMM(vspltisb, 6, 12),
10597GEN_VXFORM_SIMM(vspltish, 6, 13),
10598GEN_VXFORM_SIMM(vspltisw, 6, 14),
10599
10600#undef GEN_VXFORM_NOA
10601#define GEN_VXFORM_NOA(name, opc2, opc3) \
10602 GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
10603GEN_VXFORM_NOA(vupkhsb, 7, 8),
10604GEN_VXFORM_NOA(vupkhsh, 7, 9),
4430e076 10605GEN_VXFORM_207(vupkhsw, 7, 25),
5c55ff99
BS
10606GEN_VXFORM_NOA(vupklsb, 7, 10),
10607GEN_VXFORM_NOA(vupklsh, 7, 11),
4430e076 10608GEN_VXFORM_207(vupklsw, 7, 27),
5c55ff99
BS
10609GEN_VXFORM_NOA(vupkhpx, 7, 13),
10610GEN_VXFORM_NOA(vupklpx, 7, 15),
10611GEN_VXFORM_NOA(vrefp, 5, 4),
10612GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
0bffbc6c 10613GEN_VXFORM_NOA(vexptefp, 5, 6),
5c55ff99 10614GEN_VXFORM_NOA(vlogefp, 5, 7),
abe60a43
TM
10615GEN_VXFORM_NOA(vrfim, 5, 11),
10616GEN_VXFORM_NOA(vrfin, 5, 8),
5c55ff99 10617GEN_VXFORM_NOA(vrfip, 5, 10),
abe60a43 10618GEN_VXFORM_NOA(vrfiz, 5, 9),
5c55ff99
BS
10619
10620#undef GEN_VXFORM_UIMM
10621#define GEN_VXFORM_UIMM(name, opc2, opc3) \
10622 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
10623GEN_VXFORM_UIMM(vspltb, 6, 8),
10624GEN_VXFORM_UIMM(vsplth, 6, 9),
10625GEN_VXFORM_UIMM(vspltw, 6, 10),
10626GEN_VXFORM_UIMM(vcfux, 5, 12),
10627GEN_VXFORM_UIMM(vcfsx, 5, 13),
10628GEN_VXFORM_UIMM(vctuxs, 5, 14),
10629GEN_VXFORM_UIMM(vctsxs, 5, 15),
10630
10631#undef GEN_VAFORM_PAIRED
10632#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
10633 GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
10634GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
10635GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
10636GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
10637GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
10638GEN_VAFORM_PAIRED(vsel, vperm, 21),
10639GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
10640
e13500b3
TM
10641GEN_VXFORM_DUAL(vclzb, vpopcntb, 1, 28, PPC_NONE, PPC2_ALTIVEC_207),
10642GEN_VXFORM_DUAL(vclzh, vpopcnth, 1, 29, PPC_NONE, PPC2_ALTIVEC_207),
10643GEN_VXFORM_DUAL(vclzw, vpopcntw, 1, 30, PPC_NONE, PPC2_ALTIVEC_207),
10644GEN_VXFORM_DUAL(vclzd, vpopcntd, 1, 31, PPC_NONE, PPC2_ALTIVEC_207),
10645
4d82038e 10646GEN_VXFORM_207(vbpermq, 6, 21),
f1064f61 10647GEN_VXFORM_207(vgbbd, 6, 20),
b8476fc7
TM
10648GEN_VXFORM_207(vpmsumb, 4, 16),
10649GEN_VXFORM_207(vpmsumh, 4, 17),
10650GEN_VXFORM_207(vpmsumw, 4, 18),
10651GEN_VXFORM_207(vpmsumd, 4, 19),
f293f04a 10652
557d52fa
TM
10653GEN_VXFORM_207(vsbox, 4, 23),
10654
10655GEN_VXFORM_DUAL(vcipher, vcipherlast, 4, 20, PPC_NONE, PPC2_ALTIVEC_207),
10656GEN_VXFORM_DUAL(vncipher, vncipherlast, 4, 21, PPC_NONE, PPC2_ALTIVEC_207),
10657
57354f8f
TM
10658GEN_VXFORM_207(vshasigmaw, 1, 26),
10659GEN_VXFORM_207(vshasigmad, 1, 27),
10660
ac174549
TM
10661GEN_VXFORM_DUAL(vsldoi, vpermxor, 22, 0xFF, PPC_ALTIVEC, PPC_NONE),
10662
fa1832d7 10663GEN_HANDLER_E(lxsdx, 0x1F, 0x0C, 0x12, 0, PPC_NONE, PPC2_VSX),
cac7f0ba
TM
10664GEN_HANDLER_E(lxsiwax, 0x1F, 0x0C, 0x02, 0, PPC_NONE, PPC2_VSX207),
10665GEN_HANDLER_E(lxsiwzx, 0x1F, 0x0C, 0x00, 0, PPC_NONE, PPC2_VSX207),
10666GEN_HANDLER_E(lxsspx, 0x1F, 0x0C, 0x10, 0, PPC_NONE, PPC2_VSX207),
304af367 10667GEN_HANDLER_E(lxvd2x, 0x1F, 0x0C, 0x1A, 0, PPC_NONE, PPC2_VSX),
ca03b467 10668GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX),
897e61d1 10669GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX),
304af367 10670
9231ba9e 10671GEN_HANDLER_E(stxsdx, 0x1F, 0xC, 0x16, 0, PPC_NONE, PPC2_VSX),
e16a626b
TM
10672GEN_HANDLER_E(stxsiwx, 0x1F, 0xC, 0x04, 0, PPC_NONE, PPC2_VSX207),
10673GEN_HANDLER_E(stxsspx, 0x1F, 0xC, 0x14, 0, PPC_NONE, PPC2_VSX207),
fbed2478 10674GEN_HANDLER_E(stxvd2x, 0x1F, 0xC, 0x1E, 0, PPC_NONE, PPC2_VSX),
86e61ce3 10675GEN_HANDLER_E(stxvw4x, 0x1F, 0xC, 0x1C, 0, PPC_NONE, PPC2_VSX),
fbed2478 10676
f5c0f7f9
TM
10677GEN_HANDLER_E(mfvsrwz, 0x1F, 0x13, 0x03, 0x0000F800, PPC_NONE, PPC2_VSX207),
10678GEN_HANDLER_E(mtvsrwa, 0x1F, 0x13, 0x06, 0x0000F800, PPC_NONE, PPC2_VSX207),
10679GEN_HANDLER_E(mtvsrwz, 0x1F, 0x13, 0x07, 0x0000F800, PPC_NONE, PPC2_VSX207),
10680#if defined(TARGET_PPC64)
10681GEN_HANDLER_E(mfvsrd, 0x1F, 0x13, 0x01, 0x0000F800, PPC_NONE, PPC2_VSX207),
10682GEN_HANDLER_E(mtvsrd, 0x1F, 0x13, 0x05, 0x0000F800, PPC_NONE, PPC2_VSX207),
10683#endif
10684
df020ce0
TM
10685#undef GEN_XX2FORM
10686#define GEN_XX2FORM(name, opc2, opc3, fl2) \
10687GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
10688GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2)
10689
10690#undef GEN_XX3FORM
10691#define GEN_XX3FORM(name, opc2, opc3, fl2) \
10692GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
10693GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2), \
10694GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 0, PPC_NONE, fl2), \
10695GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 0, PPC_NONE, fl2)
10696
8f60f8e2
AJ
10697#undef GEN_XX2IFORM
10698#define GEN_XX2IFORM(name, opc2, opc3, fl2) \
10699GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 1, PPC_NONE, fl2), \
10700GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 1, PPC_NONE, fl2), \
10701GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 1, PPC_NONE, fl2), \
10702GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 1, PPC_NONE, fl2)
10703
354a6dec
TM
10704#undef GEN_XX3_RC_FORM
10705#define GEN_XX3_RC_FORM(name, opc2, opc3, fl2) \
10706GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x00, opc3 | 0x00, 0, PPC_NONE, fl2), \
10707GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x01, opc3 | 0x00, 0, PPC_NONE, fl2), \
10708GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x02, opc3 | 0x00, 0, PPC_NONE, fl2), \
10709GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x03, opc3 | 0x00, 0, PPC_NONE, fl2), \
10710GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x00, opc3 | 0x10, 0, PPC_NONE, fl2), \
10711GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x01, opc3 | 0x10, 0, PPC_NONE, fl2), \
10712GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x02, opc3 | 0x10, 0, PPC_NONE, fl2), \
10713GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0x03, opc3 | 0x10, 0, PPC_NONE, fl2)
10714
cd73f2c9
TM
10715#undef GEN_XX3FORM_DM
10716#define GEN_XX3FORM_DM(name, opc2, opc3) \
10717GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10718GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10719GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10720GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
10721GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10722GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10723GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10724GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
10725GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10726GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10727GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10728GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
10729GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
10730GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
10731GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
10732GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x0C, 0, PPC_NONE, PPC2_VSX)
10733
df020ce0
TM
10734GEN_XX2FORM(xsabsdp, 0x12, 0x15, PPC2_VSX),
10735GEN_XX2FORM(xsnabsdp, 0x12, 0x16, PPC2_VSX),
10736GEN_XX2FORM(xsnegdp, 0x12, 0x17, PPC2_VSX),
10737GEN_XX3FORM(xscpsgndp, 0x00, 0x16, PPC2_VSX),
10738
be574920
TM
10739GEN_XX2FORM(xvabsdp, 0x12, 0x1D, PPC2_VSX),
10740GEN_XX2FORM(xvnabsdp, 0x12, 0x1E, PPC2_VSX),
10741GEN_XX2FORM(xvnegdp, 0x12, 0x1F, PPC2_VSX),
10742GEN_XX3FORM(xvcpsgndp, 0x00, 0x1E, PPC2_VSX),
10743GEN_XX2FORM(xvabssp, 0x12, 0x19, PPC2_VSX),
10744GEN_XX2FORM(xvnabssp, 0x12, 0x1A, PPC2_VSX),
10745GEN_XX2FORM(xvnegsp, 0x12, 0x1B, PPC2_VSX),
10746GEN_XX3FORM(xvcpsgnsp, 0x00, 0x1A, PPC2_VSX),
79ca8a6a 10747
ee6e02c0
TM
10748GEN_XX3FORM(xsadddp, 0x00, 0x04, PPC2_VSX),
10749GEN_XX3FORM(xssubdp, 0x00, 0x05, PPC2_VSX),
5e591d88 10750GEN_XX3FORM(xsmuldp, 0x00, 0x06, PPC2_VSX),
4b98eeef 10751GEN_XX3FORM(xsdivdp, 0x00, 0x07, PPC2_VSX),
2009227f 10752GEN_XX2FORM(xsredp, 0x14, 0x05, PPC2_VSX),
d32404fe 10753GEN_XX2FORM(xssqrtdp, 0x16, 0x04, PPC2_VSX),
d3f9df8f 10754GEN_XX2FORM(xsrsqrtedp, 0x14, 0x04, PPC2_VSX),
bc80838f 10755GEN_XX3FORM(xstdivdp, 0x14, 0x07, PPC2_VSX),
5cb151ac 10756GEN_XX2FORM(xstsqrtdp, 0x14, 0x06, PPC2_VSX),
595c6eef
TM
10757GEN_XX3FORM(xsmaddadp, 0x04, 0x04, PPC2_VSX),
10758GEN_XX3FORM(xsmaddmdp, 0x04, 0x05, PPC2_VSX),
10759GEN_XX3FORM(xsmsubadp, 0x04, 0x06, PPC2_VSX),
10760GEN_XX3FORM(xsmsubmdp, 0x04, 0x07, PPC2_VSX),
10761GEN_XX3FORM(xsnmaddadp, 0x04, 0x14, PPC2_VSX),
10762GEN_XX3FORM(xsnmaddmdp, 0x04, 0x15, PPC2_VSX),
10763GEN_XX3FORM(xsnmsubadp, 0x04, 0x16, PPC2_VSX),
10764GEN_XX3FORM(xsnmsubmdp, 0x04, 0x17, PPC2_VSX),
8f60f8e2
AJ
10765GEN_XX2IFORM(xscmpodp, 0x0C, 0x05, PPC2_VSX),
10766GEN_XX2IFORM(xscmpudp, 0x0C, 0x04, PPC2_VSX),
959e9c9d
TM
10767GEN_XX3FORM(xsmaxdp, 0x00, 0x14, PPC2_VSX),
10768GEN_XX3FORM(xsmindp, 0x00, 0x15, PPC2_VSX),
ed8ac568 10769GEN_XX2FORM(xscvdpsp, 0x12, 0x10, PPC2_VSX),
7ee19fb9 10770GEN_XX2FORM(xscvdpspn, 0x16, 0x10, PPC2_VSX207),
ed8ac568 10771GEN_XX2FORM(xscvspdp, 0x12, 0x14, PPC2_VSX),
7ee19fb9 10772GEN_XX2FORM(xscvspdpn, 0x16, 0x14, PPC2_VSX207),
5177d2ca
TM
10773GEN_XX2FORM(xscvdpsxds, 0x10, 0x15, PPC2_VSX),
10774GEN_XX2FORM(xscvdpsxws, 0x10, 0x05, PPC2_VSX),
10775GEN_XX2FORM(xscvdpuxds, 0x10, 0x14, PPC2_VSX),
10776GEN_XX2FORM(xscvdpuxws, 0x10, 0x04, PPC2_VSX),
10777GEN_XX2FORM(xscvsxddp, 0x10, 0x17, PPC2_VSX),
10778GEN_XX2FORM(xscvuxddp, 0x10, 0x16, PPC2_VSX),
88e33d08
TM
10779GEN_XX2FORM(xsrdpi, 0x12, 0x04, PPC2_VSX),
10780GEN_XX2FORM(xsrdpic, 0x16, 0x06, PPC2_VSX),
10781GEN_XX2FORM(xsrdpim, 0x12, 0x07, PPC2_VSX),
10782GEN_XX2FORM(xsrdpip, 0x12, 0x06, PPC2_VSX),
10783GEN_XX2FORM(xsrdpiz, 0x12, 0x05, PPC2_VSX),
ee6e02c0 10784
3fd0aadf
TM
10785GEN_XX3FORM(xsaddsp, 0x00, 0x00, PPC2_VSX207),
10786GEN_XX3FORM(xssubsp, 0x00, 0x01, PPC2_VSX207),
ab9408a2 10787GEN_XX3FORM(xsmulsp, 0x00, 0x02, PPC2_VSX207),
b24d0b47 10788GEN_XX3FORM(xsdivsp, 0x00, 0x03, PPC2_VSX207),
2c0c52ae 10789GEN_XX2FORM(xsresp, 0x14, 0x01, PPC2_VSX207),
3d1140bf 10790GEN_XX2FORM(xsrsp, 0x12, 0x11, PPC2_VSX207),
cea4e574 10791GEN_XX2FORM(xssqrtsp, 0x16, 0x00, PPC2_VSX207),
968e76bc 10792GEN_XX2FORM(xsrsqrtesp, 0x14, 0x00, PPC2_VSX207),
f53f81e0
TM
10793GEN_XX3FORM(xsmaddasp, 0x04, 0x00, PPC2_VSX207),
10794GEN_XX3FORM(xsmaddmsp, 0x04, 0x01, PPC2_VSX207),
10795GEN_XX3FORM(xsmsubasp, 0x04, 0x02, PPC2_VSX207),
10796GEN_XX3FORM(xsmsubmsp, 0x04, 0x03, PPC2_VSX207),
10797GEN_XX3FORM(xsnmaddasp, 0x04, 0x10, PPC2_VSX207),
10798GEN_XX3FORM(xsnmaddmsp, 0x04, 0x11, PPC2_VSX207),
10799GEN_XX3FORM(xsnmsubasp, 0x04, 0x12, PPC2_VSX207),
10800GEN_XX3FORM(xsnmsubmsp, 0x04, 0x13, PPC2_VSX207),
74698350
TM
10801GEN_XX2FORM(xscvsxdsp, 0x10, 0x13, PPC2_VSX207),
10802GEN_XX2FORM(xscvuxdsp, 0x10, 0x12, PPC2_VSX207),
3fd0aadf 10803
ee6e02c0
TM
10804GEN_XX3FORM(xvadddp, 0x00, 0x0C, PPC2_VSX),
10805GEN_XX3FORM(xvsubdp, 0x00, 0x0D, PPC2_VSX),
5e591d88 10806GEN_XX3FORM(xvmuldp, 0x00, 0x0E, PPC2_VSX),
4b98eeef 10807GEN_XX3FORM(xvdivdp, 0x00, 0x0F, PPC2_VSX),
2009227f 10808GEN_XX2FORM(xvredp, 0x14, 0x0D, PPC2_VSX),
d32404fe 10809GEN_XX2FORM(xvsqrtdp, 0x16, 0x0C, PPC2_VSX),
d3f9df8f 10810GEN_XX2FORM(xvrsqrtedp, 0x14, 0x0C, PPC2_VSX),
bc80838f 10811GEN_XX3FORM(xvtdivdp, 0x14, 0x0F, PPC2_VSX),
5cb151ac 10812GEN_XX2FORM(xvtsqrtdp, 0x14, 0x0E, PPC2_VSX),
595c6eef
TM
10813GEN_XX3FORM(xvmaddadp, 0x04, 0x0C, PPC2_VSX),
10814GEN_XX3FORM(xvmaddmdp, 0x04, 0x0D, PPC2_VSX),
10815GEN_XX3FORM(xvmsubadp, 0x04, 0x0E, PPC2_VSX),
10816GEN_XX3FORM(xvmsubmdp, 0x04, 0x0F, PPC2_VSX),
10817GEN_XX3FORM(xvnmaddadp, 0x04, 0x1C, PPC2_VSX),
10818GEN_XX3FORM(xvnmaddmdp, 0x04, 0x1D, PPC2_VSX),
10819GEN_XX3FORM(xvnmsubadp, 0x04, 0x1E, PPC2_VSX),
10820GEN_XX3FORM(xvnmsubmdp, 0x04, 0x1F, PPC2_VSX),
959e9c9d
TM
10821GEN_XX3FORM(xvmaxdp, 0x00, 0x1C, PPC2_VSX),
10822GEN_XX3FORM(xvmindp, 0x00, 0x1D, PPC2_VSX),
354a6dec
TM
10823GEN_XX3_RC_FORM(xvcmpeqdp, 0x0C, 0x0C, PPC2_VSX),
10824GEN_XX3_RC_FORM(xvcmpgtdp, 0x0C, 0x0D, PPC2_VSX),
10825GEN_XX3_RC_FORM(xvcmpgedp, 0x0C, 0x0E, PPC2_VSX),
ed8ac568 10826GEN_XX2FORM(xvcvdpsp, 0x12, 0x18, PPC2_VSX),
5177d2ca
TM
10827GEN_XX2FORM(xvcvdpsxds, 0x10, 0x1D, PPC2_VSX),
10828GEN_XX2FORM(xvcvdpsxws, 0x10, 0x0D, PPC2_VSX),
10829GEN_XX2FORM(xvcvdpuxds, 0x10, 0x1C, PPC2_VSX),
10830GEN_XX2FORM(xvcvdpuxws, 0x10, 0x0C, PPC2_VSX),
10831GEN_XX2FORM(xvcvsxddp, 0x10, 0x1F, PPC2_VSX),
10832GEN_XX2FORM(xvcvuxddp, 0x10, 0x1E, PPC2_VSX),
10833GEN_XX2FORM(xvcvsxwdp, 0x10, 0x0F, PPC2_VSX),
10834GEN_XX2FORM(xvcvuxwdp, 0x10, 0x0E, PPC2_VSX),
88e33d08
TM
10835GEN_XX2FORM(xvrdpi, 0x12, 0x0C, PPC2_VSX),
10836GEN_XX2FORM(xvrdpic, 0x16, 0x0E, PPC2_VSX),
10837GEN_XX2FORM(xvrdpim, 0x12, 0x0F, PPC2_VSX),
10838GEN_XX2FORM(xvrdpip, 0x12, 0x0E, PPC2_VSX),
10839GEN_XX2FORM(xvrdpiz, 0x12, 0x0D, PPC2_VSX),
ee6e02c0
TM
10840
10841GEN_XX3FORM(xvaddsp, 0x00, 0x08, PPC2_VSX),
10842GEN_XX3FORM(xvsubsp, 0x00, 0x09, PPC2_VSX),
5e591d88 10843GEN_XX3FORM(xvmulsp, 0x00, 0x0A, PPC2_VSX),
4b98eeef 10844GEN_XX3FORM(xvdivsp, 0x00, 0x0B, PPC2_VSX),
2009227f 10845GEN_XX2FORM(xvresp, 0x14, 0x09, PPC2_VSX),
d32404fe 10846GEN_XX2FORM(xvsqrtsp, 0x16, 0x08, PPC2_VSX),
d3f9df8f 10847GEN_XX2FORM(xvrsqrtesp, 0x14, 0x08, PPC2_VSX),
bc80838f 10848GEN_XX3FORM(xvtdivsp, 0x14, 0x0B, PPC2_VSX),
5cb151ac 10849GEN_XX2FORM(xvtsqrtsp, 0x14, 0x0A, PPC2_VSX),
595c6eef
TM
10850GEN_XX3FORM(xvmaddasp, 0x04, 0x08, PPC2_VSX),
10851GEN_XX3FORM(xvmaddmsp, 0x04, 0x09, PPC2_VSX),
10852GEN_XX3FORM(xvmsubasp, 0x04, 0x0A, PPC2_VSX),
10853GEN_XX3FORM(xvmsubmsp, 0x04, 0x0B, PPC2_VSX),
10854GEN_XX3FORM(xvnmaddasp, 0x04, 0x18, PPC2_VSX),
10855GEN_XX3FORM(xvnmaddmsp, 0x04, 0x19, PPC2_VSX),
10856GEN_XX3FORM(xvnmsubasp, 0x04, 0x1A, PPC2_VSX),
10857GEN_XX3FORM(xvnmsubmsp, 0x04, 0x1B, PPC2_VSX),
959e9c9d
TM
10858GEN_XX3FORM(xvmaxsp, 0x00, 0x18, PPC2_VSX),
10859GEN_XX3FORM(xvminsp, 0x00, 0x19, PPC2_VSX),
354a6dec
TM
10860GEN_XX3_RC_FORM(xvcmpeqsp, 0x0C, 0x08, PPC2_VSX),
10861GEN_XX3_RC_FORM(xvcmpgtsp, 0x0C, 0x09, PPC2_VSX),
10862GEN_XX3_RC_FORM(xvcmpgesp, 0x0C, 0x0A, PPC2_VSX),
ed8ac568 10863GEN_XX2FORM(xvcvspdp, 0x12, 0x1C, PPC2_VSX),
5177d2ca
TM
10864GEN_XX2FORM(xvcvspsxds, 0x10, 0x19, PPC2_VSX),
10865GEN_XX2FORM(xvcvspsxws, 0x10, 0x09, PPC2_VSX),
10866GEN_XX2FORM(xvcvspuxds, 0x10, 0x18, PPC2_VSX),
10867GEN_XX2FORM(xvcvspuxws, 0x10, 0x08, PPC2_VSX),
10868GEN_XX2FORM(xvcvsxdsp, 0x10, 0x1B, PPC2_VSX),
10869GEN_XX2FORM(xvcvuxdsp, 0x10, 0x1A, PPC2_VSX),
10870GEN_XX2FORM(xvcvsxwsp, 0x10, 0x0B, PPC2_VSX),
10871GEN_XX2FORM(xvcvuxwsp, 0x10, 0x0A, PPC2_VSX),
88e33d08
TM
10872GEN_XX2FORM(xvrspi, 0x12, 0x08, PPC2_VSX),
10873GEN_XX2FORM(xvrspic, 0x16, 0x0A, PPC2_VSX),
10874GEN_XX2FORM(xvrspim, 0x12, 0x0B, PPC2_VSX),
10875GEN_XX2FORM(xvrspip, 0x12, 0x0A, PPC2_VSX),
10876GEN_XX2FORM(xvrspiz, 0x12, 0x09, PPC2_VSX),
ee6e02c0 10877
79ca8a6a
TM
10878#undef VSX_LOGICAL
10879#define VSX_LOGICAL(name, opc2, opc3, fl2) \
10880GEN_XX3FORM(name, opc2, opc3, fl2)
10881
10882VSX_LOGICAL(xxland, 0x8, 0x10, PPC2_VSX),
10883VSX_LOGICAL(xxlandc, 0x8, 0x11, PPC2_VSX),
10884VSX_LOGICAL(xxlor, 0x8, 0x12, PPC2_VSX),
10885VSX_LOGICAL(xxlxor, 0x8, 0x13, PPC2_VSX),
10886VSX_LOGICAL(xxlnor, 0x8, 0x14, PPC2_VSX),
67a33f37
TM
10887VSX_LOGICAL(xxleqv, 0x8, 0x17, PPC2_VSX207),
10888VSX_LOGICAL(xxlnand, 0x8, 0x16, PPC2_VSX207),
10889VSX_LOGICAL(xxlorc, 0x8, 0x15, PPC2_VSX207),
ce577d2e
TM
10890GEN_XX3FORM(xxmrghw, 0x08, 0x02, PPC2_VSX),
10891GEN_XX3FORM(xxmrglw, 0x08, 0x06, PPC2_VSX),
76c15fe0 10892GEN_XX2FORM(xxspltw, 0x08, 0x0A, PPC2_VSX),
acc42968 10893GEN_XX3FORM_DM(xxsldwi, 0x08, 0x00),
79ca8a6a 10894
551e3ef7
TM
10895#define GEN_XXSEL_ROW(opc3) \
10896GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x18, opc3, 0, PPC_NONE, PPC2_VSX), \
10897GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x19, opc3, 0, PPC_NONE, PPC2_VSX), \
10898GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1A, opc3, 0, PPC_NONE, PPC2_VSX), \
10899GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1B, opc3, 0, PPC_NONE, PPC2_VSX), \
10900GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1C, opc3, 0, PPC_NONE, PPC2_VSX), \
10901GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1D, opc3, 0, PPC_NONE, PPC2_VSX), \
10902GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1E, opc3, 0, PPC_NONE, PPC2_VSX), \
10903GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1F, opc3, 0, PPC_NONE, PPC2_VSX), \
10904
10905GEN_XXSEL_ROW(0x00)
10906GEN_XXSEL_ROW(0x01)
10907GEN_XXSEL_ROW(0x02)
10908GEN_XXSEL_ROW(0x03)
10909GEN_XXSEL_ROW(0x04)
10910GEN_XXSEL_ROW(0x05)
10911GEN_XXSEL_ROW(0x06)
10912GEN_XXSEL_ROW(0x07)
10913GEN_XXSEL_ROW(0x08)
10914GEN_XXSEL_ROW(0x09)
10915GEN_XXSEL_ROW(0x0A)
10916GEN_XXSEL_ROW(0x0B)
10917GEN_XXSEL_ROW(0x0C)
10918GEN_XXSEL_ROW(0x0D)
10919GEN_XXSEL_ROW(0x0E)
10920GEN_XXSEL_ROW(0x0F)
10921GEN_XXSEL_ROW(0x10)
10922GEN_XXSEL_ROW(0x11)
10923GEN_XXSEL_ROW(0x12)
10924GEN_XXSEL_ROW(0x13)
10925GEN_XXSEL_ROW(0x14)
10926GEN_XXSEL_ROW(0x15)
10927GEN_XXSEL_ROW(0x16)
10928GEN_XXSEL_ROW(0x17)
10929GEN_XXSEL_ROW(0x18)
10930GEN_XXSEL_ROW(0x19)
10931GEN_XXSEL_ROW(0x1A)
10932GEN_XXSEL_ROW(0x1B)
10933GEN_XXSEL_ROW(0x1C)
10934GEN_XXSEL_ROW(0x1D)
10935GEN_XXSEL_ROW(0x1E)
10936GEN_XXSEL_ROW(0x1F)
10937
cd73f2c9
TM
10938GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01),
10939
275e35c6
TM
10940#undef GEN_DFP_T_A_B_Rc
10941#undef GEN_DFP_BF_A_B
10942#undef GEN_DFP_BF_A_DCM
10943#undef GEN_DFP_T_B_U32_U32_Rc
10944#undef GEN_DFP_T_A_B_I32_Rc
10945#undef GEN_DFP_T_B_Rc
10946#undef GEN_DFP_T_FPR_I32_Rc
10947
10948#define _GEN_DFP_LONG(name, op1, op2, mask) \
10949GEN_HANDLER_E(name, 0x3B, op1, op2, mask, PPC_NONE, PPC2_DFP)
10950
10951#define _GEN_DFP_LONGx2(name, op1, op2, mask) \
10952GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
10953GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
10954
10955#define _GEN_DFP_LONGx4(name, op1, op2, mask) \
10956GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
10957GEN_HANDLER_E(name, 0x3B, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
10958GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
10959GEN_HANDLER_E(name, 0x3B, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
10960
10961#define _GEN_DFP_QUAD(name, op1, op2, mask) \
10962GEN_HANDLER_E(name, 0x3F, op1, op2, mask, PPC_NONE, PPC2_DFP)
10963
10964#define _GEN_DFP_QUADx2(name, op1, op2, mask) \
10965GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
10966GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
10967
10968#define _GEN_DFP_QUADx4(name, op1, op2, mask) \
10969GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
10970GEN_HANDLER_E(name, 0x3F, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
10971GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
10972GEN_HANDLER_E(name, 0x3F, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
10973
10974#define GEN_DFP_T_A_B_Rc(name, op1, op2) \
10975_GEN_DFP_LONG(name, op1, op2, 0x00000000)
10976
10977#define GEN_DFP_Tp_Ap_Bp_Rc(name, op1, op2) \
10978_GEN_DFP_QUAD(name, op1, op2, 0x00210800)
10979
10980#define GEN_DFP_Tp_A_Bp_Rc(name, op1, op2) \
10981_GEN_DFP_QUAD(name, op1, op2, 0x00200800)
10982
10983#define GEN_DFP_T_B_Rc(name, op1, op2) \
10984_GEN_DFP_LONG(name, op1, op2, 0x001F0000)
10985
10986#define GEN_DFP_Tp_Bp_Rc(name, op1, op2) \
10987_GEN_DFP_QUAD(name, op1, op2, 0x003F0800)
10988
10989#define GEN_DFP_Tp_B_Rc(name, op1, op2) \
10990_GEN_DFP_QUAD(name, op1, op2, 0x003F0000)
10991
10992#define GEN_DFP_T_Bp_Rc(name, op1, op2) \
10993_GEN_DFP_QUAD(name, op1, op2, 0x001F0800)
10994
10995#define GEN_DFP_BF_A_B(name, op1, op2) \
10996_GEN_DFP_LONG(name, op1, op2, 0x00000001)
10997
10998#define GEN_DFP_BF_Ap_Bp(name, op1, op2) \
10999_GEN_DFP_QUAD(name, op1, op2, 0x00610801)
11000
11001#define GEN_DFP_BF_A_Bp(name, op1, op2) \
11002_GEN_DFP_QUAD(name, op1, op2, 0x00600801)
11003
11004#define GEN_DFP_BF_A_DCM(name, op1, op2) \
11005_GEN_DFP_LONGx2(name, op1, op2, 0x00600001)
11006
11007#define GEN_DFP_BF_Ap_DCM(name, op1, op2) \
11008_GEN_DFP_QUADx2(name, op1, op2, 0x00610001)
11009
11010#define GEN_DFP_T_A_B_RMC_Rc(name, op1, op2) \
11011_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
11012
11013#define GEN_DFP_Tp_Ap_Bp_RMC_Rc(name, op1, op2) \
11014_GEN_DFP_QUADx4(name, op1, op2, 0x02010800)
11015
11016#define GEN_DFP_Tp_A_Bp_RMC_Rc(name, op1, op2) \
11017_GEN_DFP_QUADx4(name, op1, op2, 0x02000800)
11018
11019#define GEN_DFP_TE_T_B_RMC_Rc(name, op1, op2) \
11020_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
11021
11022#define GEN_DFP_TE_Tp_Bp_RMC_Rc(name, op1, op2) \
11023_GEN_DFP_QUADx4(name, op1, op2, 0x00200800)
11024
11025#define GEN_DFP_R_T_B_RMC_Rc(name, op1, op2) \
11026_GEN_DFP_LONGx4(name, op1, op2, 0x001E0000)
11027
11028#define GEN_DFP_R_Tp_Bp_RMC_Rc(name, op1, op2) \
11029_GEN_DFP_QUADx4(name, op1, op2, 0x003E0800)
11030
11031#define GEN_DFP_SP_T_B_Rc(name, op1, op2) \
11032_GEN_DFP_LONG(name, op1, op2, 0x00070000)
11033
11034#define GEN_DFP_SP_Tp_Bp_Rc(name, op1, op2) \
11035_GEN_DFP_QUAD(name, op1, op2, 0x00270800)
11036
11037#define GEN_DFP_S_T_B_Rc(name, op1, op2) \
11038_GEN_DFP_LONG(name, op1, op2, 0x000F0000)
11039
11040#define GEN_DFP_S_Tp_Bp_Rc(name, op1, op2) \
11041_GEN_DFP_QUAD(name, op1, op2, 0x002F0800)
11042
11043#define GEN_DFP_T_A_SH_Rc(name, op1, op2) \
11044_GEN_DFP_LONGx2(name, op1, op2, 0x00000000)
11045
11046#define GEN_DFP_Tp_Ap_SH_Rc(name, op1, op2) \
11047_GEN_DFP_QUADx2(name, op1, op2, 0x00210000)
11048
a9d7ba03
TM
11049GEN_DFP_T_A_B_Rc(dadd, 0x02, 0x00),
11050GEN_DFP_Tp_Ap_Bp_Rc(daddq, 0x02, 0x00),
2128f8a5
TM
11051GEN_DFP_T_A_B_Rc(dsub, 0x02, 0x10),
11052GEN_DFP_Tp_Ap_Bp_Rc(dsubq, 0x02, 0x10),
8de6a1cc
TM
11053GEN_DFP_T_A_B_Rc(dmul, 0x02, 0x01),
11054GEN_DFP_Tp_Ap_Bp_Rc(dmulq, 0x02, 0x01),
9024ff40
TM
11055GEN_DFP_T_A_B_Rc(ddiv, 0x02, 0x11),
11056GEN_DFP_Tp_Ap_Bp_Rc(ddivq, 0x02, 0x11),
5833505b
TM
11057GEN_DFP_BF_A_B(dcmpu, 0x02, 0x14),
11058GEN_DFP_BF_Ap_Bp(dcmpuq, 0x02, 0x14),
11059GEN_DFP_BF_A_B(dcmpo, 0x02, 0x04),
11060GEN_DFP_BF_Ap_Bp(dcmpoq, 0x02, 0x04),
e601c1ee
TM
11061GEN_DFP_BF_A_DCM(dtstdc, 0x02, 0x06),
11062GEN_DFP_BF_Ap_DCM(dtstdcq, 0x02, 0x06),
1bf9c0e1
TM
11063GEN_DFP_BF_A_DCM(dtstdg, 0x02, 0x07),
11064GEN_DFP_BF_Ap_DCM(dtstdgq, 0x02, 0x07),
f3d2b0bc
TM
11065GEN_DFP_BF_A_B(dtstex, 0x02, 0x05),
11066GEN_DFP_BF_Ap_Bp(dtstexq, 0x02, 0x05),
f6022a76
TM
11067GEN_DFP_BF_A_B(dtstsf, 0x02, 0x15),
11068GEN_DFP_BF_A_Bp(dtstsfq, 0x02, 0x15),
5826ebe2
TM
11069GEN_DFP_TE_T_B_RMC_Rc(dquai, 0x03, 0x02),
11070GEN_DFP_TE_Tp_Bp_RMC_Rc(dquaiq, 0x03, 0x02),
11071GEN_DFP_T_A_B_RMC_Rc(dqua, 0x03, 0x00),
11072GEN_DFP_Tp_Ap_Bp_RMC_Rc(dquaq, 0x03, 0x00),
512918aa
TM
11073GEN_DFP_T_A_B_RMC_Rc(drrnd, 0x03, 0x01),
11074GEN_DFP_Tp_A_Bp_RMC_Rc(drrndq, 0x03, 0x01),
97c0d930
TM
11075GEN_DFP_R_T_B_RMC_Rc(drintx, 0x03, 0x03),
11076GEN_DFP_R_Tp_Bp_RMC_Rc(drintxq, 0x03, 0x03),
11077GEN_DFP_R_T_B_RMC_Rc(drintn, 0x03, 0x07),
11078GEN_DFP_R_Tp_Bp_RMC_Rc(drintnq, 0x03, 0x07),
290d9ee5
TM
11079GEN_DFP_T_B_Rc(dctdp, 0x02, 0x08),
11080GEN_DFP_Tp_B_Rc(dctqpq, 0x02, 0x08),
ca603eb4
TM
11081GEN_DFP_T_B_Rc(drsp, 0x02, 0x18),
11082GEN_DFP_Tp_Bp_Rc(drdpq, 0x02, 0x18),
f1214193
TM
11083GEN_DFP_T_B_Rc(dcffix, 0x02, 0x19),
11084GEN_DFP_Tp_B_Rc(dcffixq, 0x02, 0x19),
bea0dd79
TM
11085GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09),
11086GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09),
7796676f
TM
11087GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a),
11088GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a),
013c3ac0
TM
11089GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a),
11090GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a),
e8a48460
TM
11091GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b),
11092GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b),
297666eb
TM
11093GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b),
11094GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b),
804e654a
TM
11095GEN_DFP_T_A_SH_Rc(dscli, 0x02, 0x02),
11096GEN_DFP_Tp_Ap_SH_Rc(dscliq, 0x02, 0x02),
11097GEN_DFP_T_A_SH_Rc(dscri, 0x02, 0x03),
11098GEN_DFP_Tp_Ap_SH_Rc(dscriq, 0x02, 0x03),
11099
5c55ff99 11100#undef GEN_SPE
70560da7
FC
11101#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
11102 GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
11103GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11104GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11105GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11106GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11107GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
11108GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
11109GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
11110GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE),
11111GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE),
11112GEN_SPE(speundef, evand, 0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
11113GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11114GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11115GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11116GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
11117GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
11118GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE),
11119GEN_SPE(speundef, evorc, 0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
11120GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11121GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11122GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11123GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11124GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
11125GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
11126GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
11127GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11128GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE),
11129GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE),
11130GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE),
11131GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE),
11132
11133GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11134GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
11135GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
11136GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11137GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11138GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11139GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11140GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11141GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11142GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11143GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11144GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11145GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11146GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11147
11148GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11149GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
11150GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
11151GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
11152GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11153GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE),
11154GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11155GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11156GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11157GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
11158GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11159GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11160GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
11161GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
11162
11163GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
11164GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11165GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE),
11166GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11167GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
11168GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11169GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
11170GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE),
11171GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11172GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11173GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11174GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
11175GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11176GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
11177GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
11178GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
5c55ff99
BS
11179
11180#undef GEN_SPEOP_LDST
11181#define GEN_SPEOP_LDST(name, opc2, sh) \
11182GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)
11183GEN_SPEOP_LDST(evldd, 0x00, 3),
11184GEN_SPEOP_LDST(evldw, 0x01, 3),
11185GEN_SPEOP_LDST(evldh, 0x02, 3),
11186GEN_SPEOP_LDST(evlhhesplat, 0x04, 1),
11187GEN_SPEOP_LDST(evlhhousplat, 0x06, 1),
11188GEN_SPEOP_LDST(evlhhossplat, 0x07, 1),
11189GEN_SPEOP_LDST(evlwhe, 0x08, 2),
11190GEN_SPEOP_LDST(evlwhou, 0x0A, 2),
11191GEN_SPEOP_LDST(evlwhos, 0x0B, 2),
11192GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2),
11193GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2),
11194
11195GEN_SPEOP_LDST(evstdd, 0x10, 3),
11196GEN_SPEOP_LDST(evstdw, 0x11, 3),
11197GEN_SPEOP_LDST(evstdh, 0x12, 3),
11198GEN_SPEOP_LDST(evstwhe, 0x18, 2),
11199GEN_SPEOP_LDST(evstwho, 0x1A, 2),
11200GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
11201GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
0ff93d11
TM
11202
11203GEN_HANDLER2_E(tbegin, "tbegin", 0x1F, 0x0E, 0x14, 0x01DFF800, \
11204 PPC_NONE, PPC2_TM),
56a84615
TM
11205GEN_HANDLER2_E(tend, "tend", 0x1F, 0x0E, 0x15, 0x01FFF800, \
11206 PPC_NONE, PPC2_TM),
11207GEN_HANDLER2_E(tabort, "tabort", 0x1F, 0x0E, 0x1C, 0x03E0F800, \
11208 PPC_NONE, PPC2_TM),
11209GEN_HANDLER2_E(tabortwc, "tabortwc", 0x1F, 0x0E, 0x18, 0x00000000, \
11210 PPC_NONE, PPC2_TM),
11211GEN_HANDLER2_E(tabortwci, "tabortwci", 0x1F, 0x0E, 0x1A, 0x00000000, \
11212 PPC_NONE, PPC2_TM),
11213GEN_HANDLER2_E(tabortdc, "tabortdc", 0x1F, 0x0E, 0x19, 0x00000000, \
11214 PPC_NONE, PPC2_TM),
11215GEN_HANDLER2_E(tabortdci, "tabortdci", 0x1F, 0x0E, 0x1B, 0x00000000, \
11216 PPC_NONE, PPC2_TM),
11217GEN_HANDLER2_E(tsr, "tsr", 0x1F, 0x0E, 0x17, 0x03DFF800, \
11218 PPC_NONE, PPC2_TM),
aeedd582
TM
11219GEN_HANDLER2_E(tcheck, "tcheck", 0x1F, 0x0E, 0x16, 0x007FF800, \
11220 PPC_NONE, PPC2_TM),
f83c2378
TM
11221GEN_HANDLER2_E(treclaim, "treclaim", 0x1F, 0x0E, 0x1D, 0x03E0F800, \
11222 PPC_NONE, PPC2_TM),
11223GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \
11224 PPC_NONE, PPC2_TM),
5c55ff99
BS
11225};
11226
0411a972 11227#include "helper_regs.h"
a1389542 11228#include "translate_init.c"
79aceca5 11229
9a64fbe4 11230/*****************************************************************************/
3fc6c082 11231/* Misc PowerPC helpers */
878096ee
AF
11232void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11233 int flags)
79aceca5 11234{
3fc6c082
FB
11235#define RGPL 4
11236#define RFPL 4
3fc6c082 11237
878096ee
AF
11238 PowerPCCPU *cpu = POWERPC_CPU(cs);
11239 CPUPPCState *env = &cpu->env;
79aceca5
FB
11240 int i;
11241
90e189ec 11242 cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR "
21e5d28a
TG
11243 TARGET_FMT_lx " XER " TARGET_FMT_lx " CPU#%d\n",
11244 env->nip, env->lr, env->ctr, cpu_read_xer(env),
11245 cs->cpu_index);
90e189ec 11246 cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF "
9fb04491
BH
11247 TARGET_FMT_lx " iidx %d didx %d\n",
11248 env->msr, env->spr[SPR_HID0],
11249 env->hflags, env->immu_idx, env->dmmu_idx);
d9bce9d9 11250#if !defined(NO_TIMER_DUMP)
9a78eead 11251 cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
76a66253 11252#if !defined(CONFIG_USER_ONLY)
9a78eead 11253 " DECR %08" PRIu32
76a66253
JM
11254#endif
11255 "\n",
077fc206 11256 cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
76a66253
JM
11257#if !defined(CONFIG_USER_ONLY)
11258 , cpu_ppc_load_decr(env)
11259#endif
11260 );
077fc206 11261#endif
76a66253 11262 for (i = 0; i < 32; i++) {
3fc6c082
FB
11263 if ((i & (RGPL - 1)) == 0)
11264 cpu_fprintf(f, "GPR%02d", i);
b11ebf64 11265 cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
3fc6c082 11266 if ((i & (RGPL - 1)) == (RGPL - 1))
7fe48483 11267 cpu_fprintf(f, "\n");
76a66253 11268 }
3fc6c082 11269 cpu_fprintf(f, "CR ");
76a66253 11270 for (i = 0; i < 8; i++)
7fe48483
FB
11271 cpu_fprintf(f, "%01x", env->crf[i]);
11272 cpu_fprintf(f, " [");
76a66253
JM
11273 for (i = 0; i < 8; i++) {
11274 char a = '-';
11275 if (env->crf[i] & 0x08)
11276 a = 'L';
11277 else if (env->crf[i] & 0x04)
11278 a = 'G';
11279 else if (env->crf[i] & 0x02)
11280 a = 'E';
7fe48483 11281 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
76a66253 11282 }
90e189ec
BS
11283 cpu_fprintf(f, " ] RES " TARGET_FMT_lx "\n",
11284 env->reserve_addr);
3fc6c082
FB
11285 for (i = 0; i < 32; i++) {
11286 if ((i & (RFPL - 1)) == 0)
11287 cpu_fprintf(f, "FPR%02d", i);
26a76461 11288 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
3fc6c082 11289 if ((i & (RFPL - 1)) == (RFPL - 1))
7fe48483 11290 cpu_fprintf(f, "\n");
79aceca5 11291 }
30304420 11292 cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
f2e63a42 11293#if !defined(CONFIG_USER_ONLY)
90dc8812
SW
11294 cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx
11295 " PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
11296 env->spr[SPR_SRR0], env->spr[SPR_SRR1],
11297 env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);
11298
11299 cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
11300 " SPRG2 " TARGET_FMT_lx " SPRG3 " TARGET_FMT_lx "\n",
11301 env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
11302 env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);
11303
11304 cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
11305 " SPRG6 " TARGET_FMT_lx " SPRG7 " TARGET_FMT_lx "\n",
11306 env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
11307 env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
11308
11309 if (env->excp_model == POWERPC_EXCP_BOOKE) {
11310 cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
11311 " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
11312 env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
11313 env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
11314
11315 cpu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
11316 " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
11317 env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
11318 env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
11319
11320 cpu_fprintf(f, " PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
11321 " IVPR " TARGET_FMT_lx " EPCR " TARGET_FMT_lx "\n",
11322 env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
11323 env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);
11324
11325 cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
11326 " EPR " TARGET_FMT_lx "\n",
11327 env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
11328 env->spr[SPR_BOOKE_EPR]);
11329
11330 /* FSL-specific */
11331 cpu_fprintf(f, " MCAR " TARGET_FMT_lx " PID1 " TARGET_FMT_lx
11332 " PID2 " TARGET_FMT_lx " SVR " TARGET_FMT_lx "\n",
11333 env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
11334 env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);
11335
11336 /*
11337 * IVORs are left out as they are large and do not change often --
11338 * they can be read with "p $ivor0", "p $ivor1", etc.
11339 */
11340 }
11341
697ab892
DG
11342#if defined(TARGET_PPC64)
11343 if (env->flags & POWERPC_FLAG_CFAR) {
11344 cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
11345 }
11346#endif
11347
90dc8812
SW
11348 switch (env->mmu_model) {
11349 case POWERPC_MMU_32B:
11350 case POWERPC_MMU_601:
11351 case POWERPC_MMU_SOFT_6xx:
11352 case POWERPC_MMU_SOFT_74xx:
11353#if defined(TARGET_PPC64)
90dc8812 11354 case POWERPC_MMU_64B:
aa4bb587 11355 case POWERPC_MMU_2_03:
ca480de6 11356 case POWERPC_MMU_2_06:
808bc3b0 11357 case POWERPC_MMU_2_06a:
aa4bb587 11358 case POWERPC_MMU_2_07:
808bc3b0 11359 case POWERPC_MMU_2_07a:
90dc8812 11360#endif
ca480de6
AB
11361 cpu_fprintf(f, " SDR1 " TARGET_FMT_lx " DAR " TARGET_FMT_lx
11362 " DSISR " TARGET_FMT_lx "\n", env->spr[SPR_SDR1],
11363 env->spr[SPR_DAR], env->spr[SPR_DSISR]);
90dc8812 11364 break;
01662f3e 11365 case POWERPC_MMU_BOOKE206:
90dc8812
SW
11366 cpu_fprintf(f, " MAS0 " TARGET_FMT_lx " MAS1 " TARGET_FMT_lx
11367 " MAS2 " TARGET_FMT_lx " MAS3 " TARGET_FMT_lx "\n",
11368 env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
11369 env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);
11370
11371 cpu_fprintf(f, " MAS4 " TARGET_FMT_lx " MAS6 " TARGET_FMT_lx
11372 " MAS7 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n",
11373 env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
11374 env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);
11375
11376 cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
11377 " TLB1CFG " TARGET_FMT_lx "\n",
11378 env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
11379 env->spr[SPR_BOOKE_TLB1CFG]);
11380 break;
11381 default:
11382 break;
11383 }
f2e63a42 11384#endif
79aceca5 11385
3fc6c082
FB
11386#undef RGPL
11387#undef RFPL
79aceca5
FB
11388}
11389
878096ee
AF
11390void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
11391 fprintf_function cpu_fprintf, int flags)
76a66253
JM
11392{
11393#if defined(DO_PPC_STATISTICS)
878096ee 11394 PowerPCCPU *cpu = POWERPC_CPU(cs);
c227f099 11395 opc_handler_t **t1, **t2, **t3, *handler;
76a66253
JM
11396 int op1, op2, op3;
11397
878096ee 11398 t1 = cpu->env.opcodes;
76a66253
JM
11399 for (op1 = 0; op1 < 64; op1++) {
11400 handler = t1[op1];
11401 if (is_indirect_opcode(handler)) {
11402 t2 = ind_table(handler);
11403 for (op2 = 0; op2 < 32; op2++) {
11404 handler = t2[op2];
11405 if (is_indirect_opcode(handler)) {
11406 t3 = ind_table(handler);
11407 for (op3 = 0; op3 < 32; op3++) {
11408 handler = t3[op3];
11409 if (handler->count == 0)
11410 continue;
11411 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
0bfcd599 11412 "%016" PRIx64 " %" PRId64 "\n",
76a66253
JM
11413 op1, op2, op3, op1, (op3 << 5) | op2,
11414 handler->oname,
11415 handler->count, handler->count);
11416 }
11417 } else {
11418 if (handler->count == 0)
11419 continue;
11420 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
0bfcd599 11421 "%016" PRIx64 " %" PRId64 "\n",
76a66253
JM
11422 op1, op2, op1, op2, handler->oname,
11423 handler->count, handler->count);
11424 }
11425 }
11426 } else {
11427 if (handler->count == 0)
11428 continue;
0bfcd599
BS
11429 cpu_fprintf(f, "%02x (%02x ) %16s: %016" PRIx64
11430 " %" PRId64 "\n",
76a66253
JM
11431 op1, op1, handler->oname,
11432 handler->count, handler->count);
11433 }
11434 }
11435#endif
11436}
11437
9a64fbe4 11438/*****************************************************************************/
4e5e1215 11439void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
79aceca5 11440{
4e5e1215 11441 PowerPCCPU *cpu = ppc_env_get_cpu(env);
ed2803da 11442 CPUState *cs = CPU(cpu);
9fddaa0c 11443 DisasContext ctx, *ctxp = &ctx;
c227f099 11444 opc_handler_t **table, *handler;
0fa85d43 11445 target_ulong pc_start;
2e70f6ef
PB
11446 int num_insns;
11447 int max_insns;
79aceca5
FB
11448
11449 pc_start = tb->pc;
046d6672 11450 ctx.nip = pc_start;
79aceca5 11451 ctx.tb = tb;
e1833e1f 11452 ctx.exception = POWERPC_EXCP_NONE;
3fc6c082 11453 ctx.spr_cb = env->spr_cb;
c47493f2 11454 ctx.pr = msr_pr;
9fb04491 11455 ctx.mem_idx = env->dmmu_idx;
932ccbdd
BH
11456#if !defined(CONFIG_USER_ONLY)
11457 ctx.hv = msr_hv || !env->has_hv_mode;
11458#endif
7d08d856
AJ
11459 ctx.insns_flags = env->insns_flags;
11460 ctx.insns_flags2 = env->insns_flags2;
76db3ba4
AJ
11461 ctx.access_type = -1;
11462 ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
e22c357b 11463 ctx.default_tcg_memop_mask = ctx.le_mode ? MO_LE : MO_BE;
d9bce9d9 11464#if defined(TARGET_PPC64)
e42a61f1 11465 ctx.sf_mode = msr_is_64bit(env, env->msr);
697ab892 11466 ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9a64fbe4 11467#endif
c5a8d8f3
BH
11468 if (env->mmu_model == POWERPC_MMU_32B ||
11469 env->mmu_model == POWERPC_MMU_601 ||
11470 (env->mmu_model & POWERPC_MMU_64B))
11471 ctx.lazy_tlb_flush = true;
11472
3cc62370 11473 ctx.fpu_enabled = msr_fp;
a9d9eb8f 11474 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
d26bfc9a
JM
11475 ctx.spe_enabled = msr_spe;
11476 else
11477 ctx.spe_enabled = 0;
a9d9eb8f
JM
11478 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
11479 ctx.altivec_enabled = msr_vr;
11480 else
11481 ctx.altivec_enabled = 0;
1f29871c
TM
11482 if ((env->flags & POWERPC_FLAG_VSX) && msr_vsx) {
11483 ctx.vsx_enabled = msr_vsx;
11484 } else {
11485 ctx.vsx_enabled = 0;
11486 }
69d1a937
TM
11487#if defined(TARGET_PPC64)
11488 if ((env->flags & POWERPC_FLAG_TM) && msr_tm) {
11489 ctx.tm_enabled = msr_tm;
11490 } else {
11491 ctx.tm_enabled = 0;
11492 }
11493#endif
d26bfc9a 11494 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8cbcb4fa 11495 ctx.singlestep_enabled = CPU_SINGLE_STEP;
d26bfc9a 11496 else
8cbcb4fa 11497 ctx.singlestep_enabled = 0;
d26bfc9a 11498 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8cbcb4fa 11499 ctx.singlestep_enabled |= CPU_BRANCH_STEP;
ed2803da 11500 if (unlikely(cs->singlestep_enabled)) {
8cbcb4fa 11501 ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
ed2803da 11502 }
3fc6c082 11503#if defined (DO_SINGLE_STEP) && 0
9a64fbe4
FB
11504 /* Single step trace mode */
11505 msr_se = 1;
11506#endif
2e70f6ef
PB
11507 num_insns = 0;
11508 max_insns = tb->cflags & CF_COUNT_MASK;
190ce7fb 11509 if (max_insns == 0) {
2e70f6ef 11510 max_insns = CF_COUNT_MASK;
190ce7fb
RH
11511 }
11512 if (max_insns > TCG_MAX_INSNS) {
11513 max_insns = TCG_MAX_INSNS;
11514 }
2e70f6ef 11515
cd42d5b2 11516 gen_tb_start(tb);
3de31797 11517 tcg_clear_temp_count();
9a64fbe4 11518 /* Set env in case of segfault during code fetch */
fe700adb 11519 while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) {
667b8e29 11520 tcg_gen_insn_start(ctx.nip);
959082fc 11521 num_insns++;
667b8e29 11522
b933066a
RH
11523 if (unlikely(cpu_breakpoint_test(cs, ctx.nip, BP_ANY))) {
11524 gen_debug_exception(ctxp);
522a0d4e
RH
11525 /* The address covered by the breakpoint must be included in
11526 [tb->pc, tb->pc + tb->size) in order to for it to be
11527 properly cleared -- thus we increment the PC here so that
11528 the logic setting tb->size below does the right thing. */
11529 ctx.nip += 4;
b933066a
RH
11530 break;
11531 }
11532
d12d51d5 11533 LOG_DISAS("----------------\n");
90e189ec 11534 LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
d12d51d5 11535 ctx.nip, ctx.mem_idx, (int)msr_ir);
959082fc 11536 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO))
2e70f6ef 11537 gen_io_start();
e22c357b 11538 if (unlikely(need_byteswap(&ctx))) {
2f5a189c 11539 ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
056401ea 11540 } else {
2f5a189c 11541 ctx.opcode = cpu_ldl_code(env, ctx.nip);
111bfab3 11542 }
d12d51d5 11543 LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9a64fbe4 11544 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
476b6d16 11545 opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
046d6672 11546 ctx.nip += 4;
3fc6c082 11547 table = env->opcodes;
79aceca5
FB
11548 handler = table[opc1(ctx.opcode)];
11549 if (is_indirect_opcode(handler)) {
11550 table = ind_table(handler);
11551 handler = table[opc2(ctx.opcode)];
11552 if (is_indirect_opcode(handler)) {
11553 table = ind_table(handler);
11554 handler = table[opc3(ctx.opcode)];
11555 }
11556 }
11557 /* Is opcode *REALLY* valid ? */
76a66253 11558 if (unlikely(handler->handler == &gen_invalid)) {
48880da6
PB
11559 qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
11560 "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
11561 opc1(ctx.opcode), opc2(ctx.opcode),
11562 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
76a66253 11563 } else {
70560da7
FC
11564 uint32_t inval;
11565
11566 if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE) && Rc(ctx.opcode))) {
11567 inval = handler->inval2;
11568 } else {
11569 inval = handler->inval1;
11570 }
11571
11572 if (unlikely((ctx.opcode & inval) != 0)) {
48880da6
PB
11573 qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
11574 "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
11575 ctx.opcode & inval, opc1(ctx.opcode),
11576 opc2(ctx.opcode), opc3(ctx.opcode),
11577 ctx.opcode, ctx.nip - 4);
e06fcd75 11578 gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
4b3686fa 11579 break;
79aceca5 11580 }
79aceca5 11581 }
4b3686fa 11582 (*(handler->handler))(&ctx);
76a66253
JM
11583#if defined(DO_PPC_STATISTICS)
11584 handler->count++;
11585#endif
9a64fbe4 11586 /* Check trace mode exceptions */
8cbcb4fa
AJ
11587 if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
11588 (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
11589 ctx.exception != POWERPC_SYSCALL &&
11590 ctx.exception != POWERPC_EXCP_TRAP &&
11591 ctx.exception != POWERPC_EXCP_BRANCH)) {
e06fcd75 11592 gen_exception(ctxp, POWERPC_EXCP_TRACE);
d26bfc9a 11593 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
ed2803da 11594 (cs->singlestep_enabled) ||
1b530a6d 11595 singlestep ||
2e70f6ef 11596 num_insns >= max_insns)) {
d26bfc9a
JM
11597 /* if we reach a page boundary or are single stepping, stop
11598 * generation
11599 */
8dd4983c 11600 break;
76a66253 11601 }
3de31797
AG
11602 if (tcg_check_temp_count()) {
11603 fprintf(stderr, "Opcode %02x %02x %02x (%08x) leaked temporaries\n",
11604 opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode),
11605 ctx.opcode);
11606 exit(1);
11607 }
3fc6c082 11608 }
2e70f6ef
PB
11609 if (tb->cflags & CF_LAST_IO)
11610 gen_io_end();
e1833e1f 11611 if (ctx.exception == POWERPC_EXCP_NONE) {
c1942362 11612 gen_goto_tb(&ctx, 0, ctx.nip);
e1833e1f 11613 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
ed2803da 11614 if (unlikely(cs->singlestep_enabled)) {
e06fcd75 11615 gen_debug_exception(ctxp);
8cbcb4fa 11616 }
76a66253 11617 /* Generate the return instruction */
57fec1fe 11618 tcg_gen_exit_tb(0);
9a64fbe4 11619 }
806f352d 11620 gen_tb_end(tb, num_insns);
0a7df5da 11621
4e5e1215
RH
11622 tb->size = ctx.nip - pc_start;
11623 tb->icount = num_insns;
11624
d9bce9d9 11625#if defined(DEBUG_DISAS)
4910e6e4
RH
11626 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
11627 && qemu_log_in_addr_range(pc_start)) {
76a66253 11628 int flags;
237c0af0 11629 flags = env->bfd_mach;
76db3ba4 11630 flags |= ctx.le_mode << 16;
93fcfe39 11631 qemu_log("IN: %s\n", lookup_symbol(pc_start));
d49190c4 11632 log_target_disas(cs, pc_start, ctx.nip - pc_start, flags);
93fcfe39 11633 qemu_log("\n");
9fddaa0c 11634 }
79aceca5 11635#endif
79aceca5
FB
11636}
11637
bad729e2
RH
11638void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb,
11639 target_ulong *data)
d2856f1a 11640{
bad729e2 11641 env->nip = data[0];
d2856f1a 11642}