]> Git Repo - qemu.git/blame - target-ppc/translate.c
Add VSX Scalar Move Instructions
[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
79aceca5 21#include "cpu.h"
76cad711 22#include "disas/disas.h"
57fec1fe 23#include "tcg-op.h"
1de7afc9 24#include "qemu/host-utils.h"
79aceca5 25
a7812ae4
PB
26#include "helper.h"
27#define GEN_HELPER 1
28#include "helper.h"
29
8cbcb4fa
AJ
30#define CPU_SINGLE_STEP 0x1
31#define CPU_BRANCH_STEP 0x2
32#define GDBSTUB_SINGLE_STEP 0x4
33
a750fc0b 34/* Include definitions for instructions classes and implementations flags */
9fddaa0c 35//#define PPC_DEBUG_DISAS
76a66253 36//#define DO_PPC_STATISTICS
79aceca5 37
d12d51d5 38#ifdef PPC_DEBUG_DISAS
93fcfe39 39# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
d12d51d5
AL
40#else
41# define LOG_DISAS(...) do { } while (0)
42#endif
a750fc0b
JM
43/*****************************************************************************/
44/* Code translation helpers */
c53be334 45
f78fb44e 46/* global register indexes */
a7812ae4 47static TCGv_ptr cpu_env;
1d542695 48static char cpu_reg_names[10*3 + 22*4 /* GPR */
f78fb44e 49#if !defined(TARGET_PPC64)
1d542695 50 + 10*4 + 22*5 /* SPE GPRh */
f78fb44e 51#endif
a5e26afa 52 + 10*4 + 22*5 /* FPR */
47e4661c 53 + 2*(10*6 + 22*7) /* AVRh, AVRl */
472b24ce 54 + 10*5 + 22*6 /* VSR */
47e4661c 55 + 8*5 /* CRF */];
f78fb44e
AJ
56static TCGv cpu_gpr[32];
57#if !defined(TARGET_PPC64)
58static TCGv cpu_gprh[32];
59#endif
a7812ae4
PB
60static TCGv_i64 cpu_fpr[32];
61static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
472b24ce 62static TCGv_i64 cpu_vsr[32];
a7812ae4 63static TCGv_i32 cpu_crf[8];
bd568f18 64static TCGv cpu_nip;
6527f6ea 65static TCGv cpu_msr;
cfdcd37a
AJ
66static TCGv cpu_ctr;
67static TCGv cpu_lr;
697ab892
DG
68#if defined(TARGET_PPC64)
69static TCGv cpu_cfar;
70#endif
da91a00f 71static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca;
cf360a32 72static TCGv cpu_reserve;
30304420 73static TCGv cpu_fpscr;
a7859e89 74static TCGv_i32 cpu_access_type;
f78fb44e 75
022c62cb 76#include "exec/gen-icount.h"
2e70f6ef
PB
77
78void ppc_translate_init(void)
79{
f78fb44e
AJ
80 int i;
81 char* p;
2dc766da 82 size_t cpu_reg_names_size;
b2437bf2 83 static int done_init = 0;
f78fb44e 84
2e70f6ef
PB
85 if (done_init)
86 return;
f78fb44e 87
a7812ae4 88 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
a7812ae4 89
f78fb44e 90 p = cpu_reg_names;
2dc766da 91 cpu_reg_names_size = sizeof(cpu_reg_names);
47e4661c
AJ
92
93 for (i = 0; i < 8; i++) {
2dc766da 94 snprintf(p, cpu_reg_names_size, "crf%d", i);
a7812ae4 95 cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
1328c2bf 96 offsetof(CPUPPCState, crf[i]), p);
47e4661c 97 p += 5;
2dc766da 98 cpu_reg_names_size -= 5;
47e4661c
AJ
99 }
100
f78fb44e 101 for (i = 0; i < 32; i++) {
2dc766da 102 snprintf(p, cpu_reg_names_size, "r%d", i);
a7812ae4 103 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
1328c2bf 104 offsetof(CPUPPCState, gpr[i]), p);
f78fb44e 105 p += (i < 10) ? 3 : 4;
2dc766da 106 cpu_reg_names_size -= (i < 10) ? 3 : 4;
f78fb44e 107#if !defined(TARGET_PPC64)
2dc766da 108 snprintf(p, cpu_reg_names_size, "r%dH", i);
a7812ae4 109 cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
1328c2bf 110 offsetof(CPUPPCState, gprh[i]), p);
f78fb44e 111 p += (i < 10) ? 4 : 5;
2dc766da 112 cpu_reg_names_size -= (i < 10) ? 4 : 5;
f78fb44e 113#endif
1d542695 114
2dc766da 115 snprintf(p, cpu_reg_names_size, "fp%d", i);
a7812ae4 116 cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
1328c2bf 117 offsetof(CPUPPCState, fpr[i]), p);
ec1ac72d 118 p += (i < 10) ? 4 : 5;
2dc766da 119 cpu_reg_names_size -= (i < 10) ? 4 : 5;
a5e26afa 120
2dc766da 121 snprintf(p, cpu_reg_names_size, "avr%dH", i);
e2542fe2 122#ifdef HOST_WORDS_BIGENDIAN
fe1e5c53 123 cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
1328c2bf 124 offsetof(CPUPPCState, avr[i].u64[0]), p);
fe1e5c53 125#else
a7812ae4 126 cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
1328c2bf 127 offsetof(CPUPPCState, avr[i].u64[1]), p);
fe1e5c53 128#endif
1d542695 129 p += (i < 10) ? 6 : 7;
2dc766da 130 cpu_reg_names_size -= (i < 10) ? 6 : 7;
ec1ac72d 131
2dc766da 132 snprintf(p, cpu_reg_names_size, "avr%dL", i);
e2542fe2 133#ifdef HOST_WORDS_BIGENDIAN
fe1e5c53 134 cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
1328c2bf 135 offsetof(CPUPPCState, avr[i].u64[1]), p);
fe1e5c53 136#else
a7812ae4 137 cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
1328c2bf 138 offsetof(CPUPPCState, avr[i].u64[0]), p);
fe1e5c53 139#endif
1d542695 140 p += (i < 10) ? 6 : 7;
2dc766da 141 cpu_reg_names_size -= (i < 10) ? 6 : 7;
472b24ce
TM
142 snprintf(p, cpu_reg_names_size, "vsr%d", i);
143 cpu_vsr[i] = tcg_global_mem_new_i64(TCG_AREG0,
144 offsetof(CPUPPCState, vsr[i]), p);
145 p += (i < 10) ? 5 : 6;
146 cpu_reg_names_size -= (i < 10) ? 5 : 6;
f78fb44e 147 }
f10dc08e 148
a7812ae4 149 cpu_nip = tcg_global_mem_new(TCG_AREG0,
1328c2bf 150 offsetof(CPUPPCState, nip), "nip");
bd568f18 151
6527f6ea 152 cpu_msr = tcg_global_mem_new(TCG_AREG0,
1328c2bf 153 offsetof(CPUPPCState, msr), "msr");
6527f6ea 154
a7812ae4 155 cpu_ctr = tcg_global_mem_new(TCG_AREG0,
1328c2bf 156 offsetof(CPUPPCState, ctr), "ctr");
cfdcd37a 157
a7812ae4 158 cpu_lr = tcg_global_mem_new(TCG_AREG0,
1328c2bf 159 offsetof(CPUPPCState, lr), "lr");
cfdcd37a 160
697ab892
DG
161#if defined(TARGET_PPC64)
162 cpu_cfar = tcg_global_mem_new(TCG_AREG0,
1328c2bf 163 offsetof(CPUPPCState, cfar), "cfar");
697ab892
DG
164#endif
165
a7812ae4 166 cpu_xer = tcg_global_mem_new(TCG_AREG0,
1328c2bf 167 offsetof(CPUPPCState, xer), "xer");
da91a00f
RH
168 cpu_so = tcg_global_mem_new(TCG_AREG0,
169 offsetof(CPUPPCState, so), "SO");
170 cpu_ov = tcg_global_mem_new(TCG_AREG0,
171 offsetof(CPUPPCState, ov), "OV");
172 cpu_ca = tcg_global_mem_new(TCG_AREG0,
173 offsetof(CPUPPCState, ca), "CA");
3d7b417e 174
cf360a32 175 cpu_reserve = tcg_global_mem_new(TCG_AREG0,
1328c2bf 176 offsetof(CPUPPCState, reserve_addr),
18b21a2f 177 "reserve_addr");
cf360a32 178
30304420
DG
179 cpu_fpscr = tcg_global_mem_new(TCG_AREG0,
180 offsetof(CPUPPCState, fpscr), "fpscr");
e1571908 181
a7859e89 182 cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
1328c2bf 183 offsetof(CPUPPCState, access_type), "access_type");
a7859e89 184
2e70f6ef
PB
185 done_init = 1;
186}
187
79aceca5
FB
188/* internal defines */
189typedef struct DisasContext {
190 struct TranslationBlock *tb;
0fa85d43 191 target_ulong nip;
79aceca5 192 uint32_t opcode;
9a64fbe4 193 uint32_t exception;
3cc62370
FB
194 /* Routine used to access memory */
195 int mem_idx;
76db3ba4 196 int access_type;
3cc62370 197 /* Translation flags */
76db3ba4 198 int le_mode;
d9bce9d9
JM
199#if defined(TARGET_PPC64)
200 int sf_mode;
697ab892 201 int has_cfar;
9a64fbe4 202#endif
3cc62370 203 int fpu_enabled;
a9d9eb8f 204 int altivec_enabled;
1f29871c 205 int vsx_enabled;
0487d6a8 206 int spe_enabled;
c227f099 207 ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
ea4e754f 208 int singlestep_enabled;
7d08d856
AJ
209 uint64_t insns_flags;
210 uint64_t insns_flags2;
79aceca5
FB
211} DisasContext;
212
79482e5a
RH
213/* True when active word size < size of target_long. */
214#ifdef TARGET_PPC64
215# define NARROW_MODE(C) (!(C)->sf_mode)
216#else
217# define NARROW_MODE(C) 0
218#endif
219
c227f099 220struct opc_handler_t {
70560da7
FC
221 /* invalid bits for instruction 1 (Rc(opcode) == 0) */
222 uint32_t inval1;
223 /* invalid bits for instruction 2 (Rc(opcode) == 1) */
224 uint32_t inval2;
9a64fbe4 225 /* instruction type */
0487d6a8 226 uint64_t type;
a5858d7a
AG
227 /* extended instruction type */
228 uint64_t type2;
79aceca5
FB
229 /* handler */
230 void (*handler)(DisasContext *ctx);
a750fc0b 231#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
b55266b5 232 const char *oname;
a750fc0b
JM
233#endif
234#if defined(DO_PPC_STATISTICS)
76a66253
JM
235 uint64_t count;
236#endif
3fc6c082 237};
79aceca5 238
636aa200 239static inline void gen_reset_fpstatus(void)
7c58044c 240{
8e703949 241 gen_helper_reset_fpstatus(cpu_env);
7c58044c
JM
242}
243
636aa200 244static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
7c58044c 245{
0f2f39c2 246 TCGv_i32 t0 = tcg_temp_new_i32();
af12906f 247
7c58044c
JM
248 if (set_fprf != 0) {
249 /* This case might be optimized later */
0f2f39c2 250 tcg_gen_movi_i32(t0, 1);
8e703949 251 gen_helper_compute_fprf(t0, cpu_env, arg, t0);
a7812ae4 252 if (unlikely(set_rc)) {
0f2f39c2 253 tcg_gen_mov_i32(cpu_crf[1], t0);
a7812ae4 254 }
8e703949 255 gen_helper_float_check_status(cpu_env);
7c58044c
JM
256 } else if (unlikely(set_rc)) {
257 /* We always need to compute fpcc */
0f2f39c2 258 tcg_gen_movi_i32(t0, 0);
8e703949 259 gen_helper_compute_fprf(t0, cpu_env, arg, t0);
0f2f39c2 260 tcg_gen_mov_i32(cpu_crf[1], t0);
7c58044c 261 }
af12906f 262
0f2f39c2 263 tcg_temp_free_i32(t0);
7c58044c
JM
264}
265
636aa200 266static inline void gen_set_access_type(DisasContext *ctx, int access_type)
a7859e89 267{
76db3ba4
AJ
268 if (ctx->access_type != access_type) {
269 tcg_gen_movi_i32(cpu_access_type, access_type);
270 ctx->access_type = access_type;
271 }
a7859e89
AJ
272}
273
636aa200 274static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
d9bce9d9 275{
e0c8f9ce
RH
276 if (NARROW_MODE(ctx)) {
277 nip = (uint32_t)nip;
278 }
279 tcg_gen_movi_tl(cpu_nip, nip);
d9bce9d9
JM
280}
281
636aa200 282static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
e06fcd75
AJ
283{
284 TCGv_i32 t0, t1;
285 if (ctx->exception == POWERPC_EXCP_NONE) {
286 gen_update_nip(ctx, ctx->nip);
287 }
288 t0 = tcg_const_i32(excp);
289 t1 = tcg_const_i32(error);
e5f17ac6 290 gen_helper_raise_exception_err(cpu_env, t0, t1);
e06fcd75
AJ
291 tcg_temp_free_i32(t0);
292 tcg_temp_free_i32(t1);
293 ctx->exception = (excp);
294}
e1833e1f 295
636aa200 296static inline void gen_exception(DisasContext *ctx, uint32_t excp)
e06fcd75
AJ
297{
298 TCGv_i32 t0;
299 if (ctx->exception == POWERPC_EXCP_NONE) {
300 gen_update_nip(ctx, ctx->nip);
301 }
302 t0 = tcg_const_i32(excp);
e5f17ac6 303 gen_helper_raise_exception(cpu_env, t0);
e06fcd75
AJ
304 tcg_temp_free_i32(t0);
305 ctx->exception = (excp);
306}
e1833e1f 307
636aa200 308static inline void gen_debug_exception(DisasContext *ctx)
e06fcd75
AJ
309{
310 TCGv_i32 t0;
5518f3a6 311
ee2b3994
SB
312 if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
313 (ctx->exception != POWERPC_EXCP_SYNC)) {
5518f3a6 314 gen_update_nip(ctx, ctx->nip);
ee2b3994 315 }
e06fcd75 316 t0 = tcg_const_i32(EXCP_DEBUG);
e5f17ac6 317 gen_helper_raise_exception(cpu_env, t0);
e06fcd75
AJ
318 tcg_temp_free_i32(t0);
319}
9a64fbe4 320
636aa200 321static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
e06fcd75
AJ
322{
323 gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
324}
a9d9eb8f 325
f24e5695 326/* Stop translation */
636aa200 327static inline void gen_stop_exception(DisasContext *ctx)
3fc6c082 328{
d9bce9d9 329 gen_update_nip(ctx, ctx->nip);
e1833e1f 330 ctx->exception = POWERPC_EXCP_STOP;
3fc6c082
FB
331}
332
f24e5695 333/* No need to update nip here, as execution flow will change */
636aa200 334static inline void gen_sync_exception(DisasContext *ctx)
2be0071f 335{
e1833e1f 336 ctx->exception = POWERPC_EXCP_SYNC;
2be0071f
FB
337}
338
79aceca5 339#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
a5858d7a
AG
340GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
341
342#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2) \
343GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
79aceca5 344
c7697e1f 345#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
a5858d7a
AG
346GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
347
348#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2) \
349GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
c7697e1f 350
c227f099 351typedef struct opcode_t {
79aceca5 352 unsigned char opc1, opc2, opc3;
1235fc06 353#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
18fba28c
FB
354 unsigned char pad[5];
355#else
356 unsigned char pad[1];
357#endif
c227f099 358 opc_handler_t handler;
b55266b5 359 const char *oname;
c227f099 360} opcode_t;
79aceca5 361
a750fc0b 362/*****************************************************************************/
79aceca5
FB
363/*** Instruction decoding ***/
364#define EXTRACT_HELPER(name, shift, nb) \
636aa200 365static inline uint32_t name(uint32_t opcode) \
79aceca5
FB
366{ \
367 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
368}
369
370#define EXTRACT_SHELPER(name, shift, nb) \
636aa200 371static inline int32_t name(uint32_t opcode) \
79aceca5 372{ \
18fba28c 373 return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
79aceca5
FB
374}
375
f9fc6d81
TM
376#define EXTRACT_HELPER_SPLIT(name, shift1, nb1, shift2, nb2) \
377static inline uint32_t name(uint32_t opcode) \
378{ \
379 return (((opcode >> (shift1)) & ((1 << (nb1)) - 1)) << nb2) | \
380 ((opcode >> (shift2)) & ((1 << (nb2)) - 1)); \
381}
79aceca5
FB
382/* Opcode part 1 */
383EXTRACT_HELPER(opc1, 26, 6);
384/* Opcode part 2 */
385EXTRACT_HELPER(opc2, 1, 5);
386/* Opcode part 3 */
387EXTRACT_HELPER(opc3, 6, 5);
388/* Update Cr0 flags */
389EXTRACT_HELPER(Rc, 0, 1);
390/* Destination */
391EXTRACT_HELPER(rD, 21, 5);
392/* Source */
393EXTRACT_HELPER(rS, 21, 5);
394/* First operand */
395EXTRACT_HELPER(rA, 16, 5);
396/* Second operand */
397EXTRACT_HELPER(rB, 11, 5);
398/* Third operand */
399EXTRACT_HELPER(rC, 6, 5);
400/*** Get CRn ***/
401EXTRACT_HELPER(crfD, 23, 3);
402EXTRACT_HELPER(crfS, 18, 3);
403EXTRACT_HELPER(crbD, 21, 5);
404EXTRACT_HELPER(crbA, 16, 5);
405EXTRACT_HELPER(crbB, 11, 5);
406/* SPR / TBL */
3fc6c082 407EXTRACT_HELPER(_SPR, 11, 10);
636aa200 408static inline uint32_t SPR(uint32_t opcode)
3fc6c082
FB
409{
410 uint32_t sprn = _SPR(opcode);
411
412 return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
413}
79aceca5
FB
414/*** Get constants ***/
415EXTRACT_HELPER(IMM, 12, 8);
416/* 16 bits signed immediate value */
417EXTRACT_SHELPER(SIMM, 0, 16);
418/* 16 bits unsigned immediate value */
419EXTRACT_HELPER(UIMM, 0, 16);
21d21583
AJ
420/* 5 bits signed immediate value */
421EXTRACT_HELPER(SIMM5, 16, 5);
27a4edb3
AJ
422/* 5 bits signed immediate value */
423EXTRACT_HELPER(UIMM5, 16, 5);
79aceca5
FB
424/* Bit count */
425EXTRACT_HELPER(NB, 11, 5);
426/* Shift count */
427EXTRACT_HELPER(SH, 11, 5);
cd633b10
AJ
428/* Vector shift count */
429EXTRACT_HELPER(VSH, 6, 4);
79aceca5
FB
430/* Mask start */
431EXTRACT_HELPER(MB, 6, 5);
432/* Mask end */
433EXTRACT_HELPER(ME, 1, 5);
fb0eaffc
FB
434/* Trap operand */
435EXTRACT_HELPER(TO, 21, 5);
79aceca5
FB
436
437EXTRACT_HELPER(CRM, 12, 8);
79aceca5 438EXTRACT_HELPER(SR, 16, 4);
7d08d856
AJ
439
440/* mtfsf/mtfsfi */
779f6590 441EXTRACT_HELPER(FPBF, 23, 3);
e4bb997e 442EXTRACT_HELPER(FPIMM, 12, 4);
779f6590 443EXTRACT_HELPER(FPL, 25, 1);
7d08d856
AJ
444EXTRACT_HELPER(FPFLM, 17, 8);
445EXTRACT_HELPER(FPW, 16, 1);
fb0eaffc 446
79aceca5
FB
447/*** Jump target decoding ***/
448/* Displacement */
449EXTRACT_SHELPER(d, 0, 16);
450/* Immediate address */
636aa200 451static inline target_ulong LI(uint32_t opcode)
79aceca5
FB
452{
453 return (opcode >> 0) & 0x03FFFFFC;
454}
455
636aa200 456static inline uint32_t BD(uint32_t opcode)
79aceca5
FB
457{
458 return (opcode >> 0) & 0xFFFC;
459}
460
461EXTRACT_HELPER(BO, 21, 5);
462EXTRACT_HELPER(BI, 16, 5);
463/* Absolute/relative address */
464EXTRACT_HELPER(AA, 1, 1);
465/* Link */
466EXTRACT_HELPER(LK, 0, 1);
467
468/* Create a mask between <start> and <end> bits */
636aa200 469static inline target_ulong MASK(uint32_t start, uint32_t end)
79aceca5 470{
76a66253 471 target_ulong ret;
79aceca5 472
76a66253
JM
473#if defined(TARGET_PPC64)
474 if (likely(start == 0)) {
6f2d8978 475 ret = UINT64_MAX << (63 - end);
76a66253 476 } else if (likely(end == 63)) {
6f2d8978 477 ret = UINT64_MAX >> start;
76a66253
JM
478 }
479#else
480 if (likely(start == 0)) {
6f2d8978 481 ret = UINT32_MAX << (31 - end);
76a66253 482 } else if (likely(end == 31)) {
6f2d8978 483 ret = UINT32_MAX >> start;
76a66253
JM
484 }
485#endif
486 else {
487 ret = (((target_ulong)(-1ULL)) >> (start)) ^
488 (((target_ulong)(-1ULL) >> (end)) >> 1);
489 if (unlikely(start > end))
490 return ~ret;
491 }
79aceca5
FB
492
493 return ret;
494}
495
f9fc6d81
TM
496EXTRACT_HELPER_SPLIT(xT, 0, 1, 21, 5);
497EXTRACT_HELPER_SPLIT(xS, 0, 1, 21, 5);
498EXTRACT_HELPER_SPLIT(xA, 2, 1, 16, 5);
499EXTRACT_HELPER_SPLIT(xB, 1, 1, 11, 5);
500EXTRACT_HELPER(DM, 8, 2);
a750fc0b 501/*****************************************************************************/
a750fc0b 502/* PowerPC instructions table */
933dc6eb 503
76a66253 504#if defined(DO_PPC_STATISTICS)
a5858d7a 505#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 506{ \
79aceca5
FB
507 .opc1 = op1, \
508 .opc2 = op2, \
509 .opc3 = op3, \
18fba28c 510 .pad = { 0, }, \
79aceca5 511 .handler = { \
70560da7
FC
512 .inval1 = invl, \
513 .type = _typ, \
514 .type2 = _typ2, \
515 .handler = &gen_##name, \
516 .oname = stringify(name), \
517 }, \
518 .oname = stringify(name), \
519}
520#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \
521{ \
522 .opc1 = op1, \
523 .opc2 = op2, \
524 .opc3 = op3, \
525 .pad = { 0, }, \
526 .handler = { \
527 .inval1 = invl1, \
528 .inval2 = invl2, \
9a64fbe4 529 .type = _typ, \
a5858d7a 530 .type2 = _typ2, \
79aceca5 531 .handler = &gen_##name, \
76a66253 532 .oname = stringify(name), \
79aceca5 533 }, \
3fc6c082 534 .oname = stringify(name), \
79aceca5 535}
a5858d7a 536#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 537{ \
c7697e1f
JM
538 .opc1 = op1, \
539 .opc2 = op2, \
540 .opc3 = op3, \
541 .pad = { 0, }, \
542 .handler = { \
70560da7 543 .inval1 = invl, \
c7697e1f 544 .type = _typ, \
a5858d7a 545 .type2 = _typ2, \
c7697e1f
JM
546 .handler = &gen_##name, \
547 .oname = onam, \
548 }, \
549 .oname = onam, \
550}
76a66253 551#else
a5858d7a 552#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 553{ \
c7697e1f
JM
554 .opc1 = op1, \
555 .opc2 = op2, \
556 .opc3 = op3, \
557 .pad = { 0, }, \
558 .handler = { \
70560da7
FC
559 .inval1 = invl, \
560 .type = _typ, \
561 .type2 = _typ2, \
562 .handler = &gen_##name, \
563 }, \
564 .oname = stringify(name), \
565}
566#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \
567{ \
568 .opc1 = op1, \
569 .opc2 = op2, \
570 .opc3 = op3, \
571 .pad = { 0, }, \
572 .handler = { \
573 .inval1 = invl1, \
574 .inval2 = invl2, \
c7697e1f 575 .type = _typ, \
a5858d7a 576 .type2 = _typ2, \
c7697e1f 577 .handler = &gen_##name, \
5c55ff99
BS
578 }, \
579 .oname = stringify(name), \
580}
a5858d7a 581#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99
BS
582{ \
583 .opc1 = op1, \
584 .opc2 = op2, \
585 .opc3 = op3, \
586 .pad = { 0, }, \
587 .handler = { \
70560da7 588 .inval1 = invl, \
5c55ff99 589 .type = _typ, \
a5858d7a 590 .type2 = _typ2, \
5c55ff99
BS
591 .handler = &gen_##name, \
592 }, \
593 .oname = onam, \
594}
595#endif
2e610050 596
5c55ff99 597/* SPR load/store helpers */
636aa200 598static inline void gen_load_spr(TCGv t, int reg)
5c55ff99 599{
1328c2bf 600 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
5c55ff99 601}
2e610050 602
636aa200 603static inline void gen_store_spr(int reg, TCGv t)
5c55ff99 604{
1328c2bf 605 tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
5c55ff99 606}
2e610050 607
54623277 608/* Invalid instruction */
99e300ef 609static void gen_invalid(DisasContext *ctx)
9a64fbe4 610{
e06fcd75 611 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
9a64fbe4
FB
612}
613
c227f099 614static opc_handler_t invalid_handler = {
70560da7
FC
615 .inval1 = 0xFFFFFFFF,
616 .inval2 = 0xFFFFFFFF,
9a64fbe4 617 .type = PPC_NONE,
a5858d7a 618 .type2 = PPC_NONE,
79aceca5
FB
619 .handler = gen_invalid,
620};
621
e1571908
AJ
622/*** Integer comparison ***/
623
636aa200 624static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
e1571908 625{
2fdcb629
RH
626 TCGv t0 = tcg_temp_new();
627 TCGv_i32 t1 = tcg_temp_new_i32();
e1571908 628
da91a00f 629 tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
e1571908 630
2fdcb629
RH
631 tcg_gen_setcond_tl((s ? TCG_COND_LT: TCG_COND_LTU), t0, arg0, arg1);
632 tcg_gen_trunc_tl_i32(t1, t0);
633 tcg_gen_shli_i32(t1, t1, CRF_LT);
634 tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
635
636 tcg_gen_setcond_tl((s ? TCG_COND_GT: TCG_COND_GTU), t0, arg0, arg1);
637 tcg_gen_trunc_tl_i32(t1, t0);
638 tcg_gen_shli_i32(t1, t1, CRF_GT);
639 tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
640
641 tcg_gen_setcond_tl(TCG_COND_EQ, t0, arg0, arg1);
642 tcg_gen_trunc_tl_i32(t1, t0);
643 tcg_gen_shli_i32(t1, t1, CRF_EQ);
644 tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1);
645
646 tcg_temp_free(t0);
647 tcg_temp_free_i32(t1);
e1571908
AJ
648}
649
636aa200 650static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 651{
2fdcb629 652 TCGv t0 = tcg_const_tl(arg1);
ea363694
AJ
653 gen_op_cmp(arg0, t0, s, crf);
654 tcg_temp_free(t0);
e1571908
AJ
655}
656
636aa200 657static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
e1571908 658{
ea363694 659 TCGv t0, t1;
2fdcb629
RH
660 t0 = tcg_temp_new();
661 t1 = tcg_temp_new();
e1571908 662 if (s) {
ea363694
AJ
663 tcg_gen_ext32s_tl(t0, arg0);
664 tcg_gen_ext32s_tl(t1, arg1);
e1571908 665 } else {
ea363694
AJ
666 tcg_gen_ext32u_tl(t0, arg0);
667 tcg_gen_ext32u_tl(t1, arg1);
e1571908 668 }
ea363694
AJ
669 gen_op_cmp(t0, t1, s, crf);
670 tcg_temp_free(t1);
671 tcg_temp_free(t0);
e1571908
AJ
672}
673
636aa200 674static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 675{
2fdcb629 676 TCGv t0 = tcg_const_tl(arg1);
ea363694
AJ
677 gen_op_cmp32(arg0, t0, s, crf);
678 tcg_temp_free(t0);
e1571908 679}
e1571908 680
636aa200 681static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
e1571908 682{
02765534 683 if (NARROW_MODE(ctx)) {
e1571908 684 gen_op_cmpi32(reg, 0, 1, 0);
02765534 685 } else {
e1571908 686 gen_op_cmpi(reg, 0, 1, 0);
02765534 687 }
e1571908
AJ
688}
689
690/* cmp */
99e300ef 691static void gen_cmp(DisasContext *ctx)
e1571908 692{
36f48d9c 693 if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
e1571908
AJ
694 gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
695 1, crfD(ctx->opcode));
36f48d9c
AG
696 } else {
697 gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
698 1, crfD(ctx->opcode));
02765534 699 }
e1571908
AJ
700}
701
702/* cmpi */
99e300ef 703static void gen_cmpi(DisasContext *ctx)
e1571908 704{
36f48d9c 705 if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
e1571908
AJ
706 gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
707 1, crfD(ctx->opcode));
36f48d9c
AG
708 } else {
709 gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
710 1, crfD(ctx->opcode));
02765534 711 }
e1571908
AJ
712}
713
714/* cmpl */
99e300ef 715static void gen_cmpl(DisasContext *ctx)
e1571908 716{
36f48d9c 717 if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
e1571908
AJ
718 gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
719 0, crfD(ctx->opcode));
36f48d9c
AG
720 } else {
721 gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
722 0, crfD(ctx->opcode));
02765534 723 }
e1571908
AJ
724}
725
726/* cmpli */
99e300ef 727static void gen_cmpli(DisasContext *ctx)
e1571908 728{
36f48d9c 729 if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) {
e1571908
AJ
730 gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
731 0, crfD(ctx->opcode));
36f48d9c
AG
732 } else {
733 gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
734 0, crfD(ctx->opcode));
02765534 735 }
e1571908
AJ
736}
737
738/* isel (PowerPC 2.03 specification) */
99e300ef 739static void gen_isel(DisasContext *ctx)
e1571908
AJ
740{
741 int l1, l2;
742 uint32_t bi = rC(ctx->opcode);
743 uint32_t mask;
a7812ae4 744 TCGv_i32 t0;
e1571908
AJ
745
746 l1 = gen_new_label();
747 l2 = gen_new_label();
748
749 mask = 1 << (3 - (bi & 0x03));
a7812ae4 750 t0 = tcg_temp_new_i32();
fea0c503
AJ
751 tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
752 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
e1571908
AJ
753 if (rA(ctx->opcode) == 0)
754 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
755 else
756 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
757 tcg_gen_br(l2);
758 gen_set_label(l1);
759 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
760 gen_set_label(l2);
a7812ae4 761 tcg_temp_free_i32(t0);
e1571908
AJ
762}
763
fcfda20f
AJ
764/* cmpb: PowerPC 2.05 specification */
765static void gen_cmpb(DisasContext *ctx)
766{
767 gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
768 cpu_gpr[rB(ctx->opcode)]);
769}
770
79aceca5 771/*** Integer arithmetic ***/
79aceca5 772
636aa200
BS
773static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
774 TCGv arg1, TCGv arg2, int sub)
74637406 775{
ffe30937 776 TCGv t0 = tcg_temp_new();
79aceca5 777
8e7a6db9 778 tcg_gen_xor_tl(cpu_ov, arg0, arg2);
74637406 779 tcg_gen_xor_tl(t0, arg1, arg2);
ffe30937
RH
780 if (sub) {
781 tcg_gen_and_tl(cpu_ov, cpu_ov, t0);
782 } else {
783 tcg_gen_andc_tl(cpu_ov, cpu_ov, t0);
784 }
785 tcg_temp_free(t0);
02765534 786 if (NARROW_MODE(ctx)) {
ffe30937
RH
787 tcg_gen_ext32s_tl(cpu_ov, cpu_ov);
788 }
ffe30937
RH
789 tcg_gen_shri_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1);
790 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
79aceca5
FB
791}
792
74637406 793/* Common add function */
636aa200 794static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
b5a73f8d
RH
795 TCGv arg2, bool add_ca, bool compute_ca,
796 bool compute_ov, bool compute_rc0)
74637406 797{
b5a73f8d 798 TCGv t0 = ret;
d9bce9d9 799
752d634e 800 if (compute_ca || compute_ov) {
146de60d 801 t0 = tcg_temp_new();
74637406 802 }
79aceca5 803
da91a00f 804 if (compute_ca) {
79482e5a 805 if (NARROW_MODE(ctx)) {
752d634e
RH
806 /* Caution: a non-obvious corner case of the spec is that we
807 must produce the *entire* 64-bit addition, but produce the
808 carry into bit 32. */
79482e5a 809 TCGv t1 = tcg_temp_new();
752d634e
RH
810 tcg_gen_xor_tl(t1, arg1, arg2); /* add without carry */
811 tcg_gen_add_tl(t0, arg1, arg2);
79482e5a
RH
812 if (add_ca) {
813 tcg_gen_add_tl(t0, t0, cpu_ca);
814 }
752d634e
RH
815 tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changed w/ carry */
816 tcg_temp_free(t1);
817 tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */
818 tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
b5a73f8d 819 } else {
79482e5a
RH
820 TCGv zero = tcg_const_tl(0);
821 if (add_ca) {
822 tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero);
823 tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero);
824 } else {
825 tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero);
826 }
827 tcg_temp_free(zero);
b5a73f8d 828 }
b5a73f8d
RH
829 } else {
830 tcg_gen_add_tl(t0, arg1, arg2);
831 if (add_ca) {
832 tcg_gen_add_tl(t0, t0, cpu_ca);
833 }
da91a00f 834 }
79aceca5 835
74637406
AJ
836 if (compute_ov) {
837 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
838 }
b5a73f8d 839 if (unlikely(compute_rc0)) {
74637406 840 gen_set_Rc0(ctx, t0);
b5a73f8d 841 }
74637406 842
a7812ae4 843 if (!TCGV_EQUAL(t0, ret)) {
74637406
AJ
844 tcg_gen_mov_tl(ret, t0);
845 tcg_temp_free(t0);
846 }
39dd32ee 847}
74637406
AJ
848/* Add functions with two operands */
849#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
b5a73f8d 850static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
851{ \
852 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
853 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
b5a73f8d 854 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
855}
856/* Add functions with one operand and one immediate */
857#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
858 add_ca, compute_ca, compute_ov) \
b5a73f8d 859static void glue(gen_, name)(DisasContext *ctx) \
74637406 860{ \
b5a73f8d 861 TCGv t0 = tcg_const_tl(const_val); \
74637406
AJ
862 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
863 cpu_gpr[rA(ctx->opcode)], t0, \
b5a73f8d 864 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
865 tcg_temp_free(t0); \
866}
867
868/* add add. addo addo. */
869GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
870GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
871/* addc addc. addco addco. */
872GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
873GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
874/* adde adde. addeo addeo. */
875GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
876GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
877/* addme addme. addmeo addmeo. */
878GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
879GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
880/* addze addze. addzeo addzeo.*/
881GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
882GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
883/* addi */
99e300ef 884static void gen_addi(DisasContext *ctx)
d9bce9d9 885{
74637406
AJ
886 target_long simm = SIMM(ctx->opcode);
887
888 if (rA(ctx->opcode) == 0) {
889 /* li case */
890 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
891 } else {
b5a73f8d
RH
892 tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
893 cpu_gpr[rA(ctx->opcode)], simm);
74637406 894 }
d9bce9d9 895}
74637406 896/* addic addic.*/
b5a73f8d 897static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
d9bce9d9 898{
b5a73f8d
RH
899 TCGv c = tcg_const_tl(SIMM(ctx->opcode));
900 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
901 c, 0, 1, 0, compute_rc0);
902 tcg_temp_free(c);
d9bce9d9 903}
99e300ef
BS
904
905static void gen_addic(DisasContext *ctx)
d9bce9d9 906{
b5a73f8d 907 gen_op_addic(ctx, 0);
d9bce9d9 908}
e8eaa2c0
BS
909
910static void gen_addic_(DisasContext *ctx)
d9bce9d9 911{
b5a73f8d 912 gen_op_addic(ctx, 1);
d9bce9d9 913}
99e300ef 914
54623277 915/* addis */
99e300ef 916static void gen_addis(DisasContext *ctx)
d9bce9d9 917{
74637406
AJ
918 target_long simm = SIMM(ctx->opcode);
919
920 if (rA(ctx->opcode) == 0) {
921 /* lis case */
922 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
923 } else {
b5a73f8d
RH
924 tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
925 cpu_gpr[rA(ctx->opcode)], simm << 16);
74637406 926 }
d9bce9d9 927}
74637406 928
636aa200
BS
929static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
930 TCGv arg2, int sign, int compute_ov)
d9bce9d9 931{
2ef1b120
AJ
932 int l1 = gen_new_label();
933 int l2 = gen_new_label();
a7812ae4
PB
934 TCGv_i32 t0 = tcg_temp_local_new_i32();
935 TCGv_i32 t1 = tcg_temp_local_new_i32();
74637406 936
2ef1b120
AJ
937 tcg_gen_trunc_tl_i32(t0, arg1);
938 tcg_gen_trunc_tl_i32(t1, arg2);
939 tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
74637406 940 if (sign) {
2ef1b120
AJ
941 int l3 = gen_new_label();
942 tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
943 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
74637406 944 gen_set_label(l3);
2ef1b120 945 tcg_gen_div_i32(t0, t0, t1);
74637406 946 } else {
2ef1b120 947 tcg_gen_divu_i32(t0, t0, t1);
74637406
AJ
948 }
949 if (compute_ov) {
da91a00f 950 tcg_gen_movi_tl(cpu_ov, 0);
74637406
AJ
951 }
952 tcg_gen_br(l2);
953 gen_set_label(l1);
954 if (sign) {
2ef1b120 955 tcg_gen_sari_i32(t0, t0, 31);
74637406
AJ
956 } else {
957 tcg_gen_movi_i32(t0, 0);
958 }
959 if (compute_ov) {
da91a00f
RH
960 tcg_gen_movi_tl(cpu_ov, 1);
961 tcg_gen_movi_tl(cpu_so, 1);
74637406
AJ
962 }
963 gen_set_label(l2);
2ef1b120 964 tcg_gen_extu_i32_tl(ret, t0);
a7812ae4
PB
965 tcg_temp_free_i32(t0);
966 tcg_temp_free_i32(t1);
74637406
AJ
967 if (unlikely(Rc(ctx->opcode) != 0))
968 gen_set_Rc0(ctx, ret);
d9bce9d9 969}
74637406
AJ
970/* Div functions */
971#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
99e300ef 972static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
973{ \
974 gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)], \
975 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
976 sign, compute_ov); \
977}
978/* divwu divwu. divwuo divwuo. */
979GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
980GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
981/* divw divw. divwo divwo. */
982GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
983GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
d9bce9d9 984#if defined(TARGET_PPC64)
636aa200
BS
985static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
986 TCGv arg2, int sign, int compute_ov)
d9bce9d9 987{
2ef1b120
AJ
988 int l1 = gen_new_label();
989 int l2 = gen_new_label();
74637406
AJ
990
991 tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
992 if (sign) {
2ef1b120 993 int l3 = gen_new_label();
74637406
AJ
994 tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
995 tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
996 gen_set_label(l3);
74637406
AJ
997 tcg_gen_div_i64(ret, arg1, arg2);
998 } else {
999 tcg_gen_divu_i64(ret, arg1, arg2);
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) {
1007 tcg_gen_sari_i64(ret, arg1, 63);
1008 } else {
1009 tcg_gen_movi_i64(ret, 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);
1016 if (unlikely(Rc(ctx->opcode) != 0))
1017 gen_set_Rc0(ctx, ret);
d9bce9d9 1018}
74637406 1019#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
99e300ef 1020static void glue(gen_, name)(DisasContext *ctx) \
74637406 1021{ \
2ef1b120
AJ
1022 gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)], \
1023 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1024 sign, compute_ov); \
74637406
AJ
1025}
1026/* divwu divwu. divwuo divwuo. */
1027GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1028GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1029/* divw divw. divwo divwo. */
1030GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1031GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
d9bce9d9 1032#endif
74637406
AJ
1033
1034/* mulhw mulhw. */
99e300ef 1035static void gen_mulhw(DisasContext *ctx)
d9bce9d9 1036{
23ad1d5d
RH
1037 TCGv_i32 t0 = tcg_temp_new_i32();
1038 TCGv_i32 t1 = tcg_temp_new_i32();
74637406 1039
23ad1d5d
RH
1040 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1041 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1042 tcg_gen_muls2_i32(t0, t1, t0, t1);
1043 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1044 tcg_temp_free_i32(t0);
1045 tcg_temp_free_i32(t1);
74637406
AJ
1046 if (unlikely(Rc(ctx->opcode) != 0))
1047 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1048}
99e300ef 1049
54623277 1050/* mulhwu mulhwu. */
99e300ef 1051static void gen_mulhwu(DisasContext *ctx)
d9bce9d9 1052{
23ad1d5d
RH
1053 TCGv_i32 t0 = tcg_temp_new_i32();
1054 TCGv_i32 t1 = tcg_temp_new_i32();
74637406 1055
23ad1d5d
RH
1056 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1057 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1058 tcg_gen_mulu2_i32(t0, t1, t0, t1);
1059 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1060 tcg_temp_free_i32(t0);
1061 tcg_temp_free_i32(t1);
74637406
AJ
1062 if (unlikely(Rc(ctx->opcode) != 0))
1063 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1064}
99e300ef 1065
54623277 1066/* mullw mullw. */
99e300ef 1067static void gen_mullw(DisasContext *ctx)
d9bce9d9 1068{
74637406
AJ
1069 tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1070 cpu_gpr[rB(ctx->opcode)]);
1e4c090f 1071 tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
74637406
AJ
1072 if (unlikely(Rc(ctx->opcode) != 0))
1073 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1074}
99e300ef 1075
54623277 1076/* mullwo mullwo. */
99e300ef 1077static void gen_mullwo(DisasContext *ctx)
d9bce9d9 1078{
e4a2c846
RH
1079 TCGv_i32 t0 = tcg_temp_new_i32();
1080 TCGv_i32 t1 = tcg_temp_new_i32();
74637406 1081
e4a2c846
RH
1082 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1083 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1084 tcg_gen_muls2_i32(t0, t1, t0, t1);
1085 tcg_gen_ext_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
1086
1087 tcg_gen_sari_i32(t0, t0, 31);
1088 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1);
1089 tcg_gen_extu_i32_tl(cpu_ov, t0);
1090 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1091
1092 tcg_temp_free_i32(t0);
1093 tcg_temp_free_i32(t1);
74637406
AJ
1094 if (unlikely(Rc(ctx->opcode) != 0))
1095 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1096}
99e300ef 1097
54623277 1098/* mulli */
99e300ef 1099static void gen_mulli(DisasContext *ctx)
d9bce9d9 1100{
74637406
AJ
1101 tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1102 SIMM(ctx->opcode));
d9bce9d9 1103}
23ad1d5d 1104
d9bce9d9 1105#if defined(TARGET_PPC64)
74637406 1106/* mulhd mulhd. */
23ad1d5d
RH
1107static void gen_mulhd(DisasContext *ctx)
1108{
1109 TCGv lo = tcg_temp_new();
1110 tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)],
1111 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1112 tcg_temp_free(lo);
1113 if (unlikely(Rc(ctx->opcode) != 0)) {
1114 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1115 }
1116}
1117
74637406 1118/* mulhdu mulhdu. */
23ad1d5d
RH
1119static void gen_mulhdu(DisasContext *ctx)
1120{
1121 TCGv lo = tcg_temp_new();
1122 tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)],
1123 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1124 tcg_temp_free(lo);
1125 if (unlikely(Rc(ctx->opcode) != 0)) {
1126 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1127 }
1128}
99e300ef 1129
54623277 1130/* mulld mulld. */
99e300ef 1131static void gen_mulld(DisasContext *ctx)
d9bce9d9 1132{
74637406
AJ
1133 tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1134 cpu_gpr[rB(ctx->opcode)]);
1135 if (unlikely(Rc(ctx->opcode) != 0))
1136 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1137}
d15f74fb 1138
74637406 1139/* mulldo mulldo. */
d15f74fb
BS
1140static void gen_mulldo(DisasContext *ctx)
1141{
1142 gen_helper_mulldo(cpu_gpr[rD(ctx->opcode)], cpu_env,
1143 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
1144 if (unlikely(Rc(ctx->opcode) != 0)) {
1145 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
1146 }
1147}
d9bce9d9 1148#endif
74637406 1149
74637406 1150/* Common subf function */
636aa200 1151static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
b5a73f8d
RH
1152 TCGv arg2, bool add_ca, bool compute_ca,
1153 bool compute_ov, bool compute_rc0)
79aceca5 1154{
b5a73f8d 1155 TCGv t0 = ret;
79aceca5 1156
752d634e 1157 if (compute_ca || compute_ov) {
b5a73f8d 1158 t0 = tcg_temp_new();
da91a00f 1159 }
74637406 1160
79482e5a
RH
1161 if (compute_ca) {
1162 /* dest = ~arg1 + arg2 [+ ca]. */
1163 if (NARROW_MODE(ctx)) {
752d634e
RH
1164 /* Caution: a non-obvious corner case of the spec is that we
1165 must produce the *entire* 64-bit addition, but produce the
1166 carry into bit 32. */
79482e5a 1167 TCGv inv1 = tcg_temp_new();
752d634e 1168 TCGv t1 = tcg_temp_new();
79482e5a 1169 tcg_gen_not_tl(inv1, arg1);
79482e5a 1170 if (add_ca) {
752d634e 1171 tcg_gen_add_tl(t0, arg2, cpu_ca);
79482e5a 1172 } else {
752d634e 1173 tcg_gen_addi_tl(t0, arg2, 1);
79482e5a 1174 }
752d634e 1175 tcg_gen_xor_tl(t1, arg2, inv1); /* add without carry */
79482e5a 1176 tcg_gen_add_tl(t0, t0, inv1);
752d634e
RH
1177 tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changes w/ carry */
1178 tcg_temp_free(t1);
1179 tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */
1180 tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
79482e5a 1181 } else if (add_ca) {
08f4a0f7
RH
1182 TCGv zero, inv1 = tcg_temp_new();
1183 tcg_gen_not_tl(inv1, arg1);
b5a73f8d
RH
1184 zero = tcg_const_tl(0);
1185 tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero);
08f4a0f7 1186 tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero);
b5a73f8d 1187 tcg_temp_free(zero);
08f4a0f7 1188 tcg_temp_free(inv1);
b5a73f8d 1189 } else {
79482e5a 1190 tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
b5a73f8d 1191 tcg_gen_sub_tl(t0, arg2, arg1);
b5a73f8d 1192 }
79482e5a
RH
1193 } else if (add_ca) {
1194 /* Since we're ignoring carry-out, we can simplify the
1195 standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1. */
1196 tcg_gen_sub_tl(t0, arg2, arg1);
1197 tcg_gen_add_tl(t0, t0, cpu_ca);
1198 tcg_gen_subi_tl(t0, t0, 1);
79aceca5 1199 } else {
b5a73f8d 1200 tcg_gen_sub_tl(t0, arg2, arg1);
74637406 1201 }
b5a73f8d 1202
74637406
AJ
1203 if (compute_ov) {
1204 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1205 }
b5a73f8d 1206 if (unlikely(compute_rc0)) {
74637406 1207 gen_set_Rc0(ctx, t0);
b5a73f8d 1208 }
74637406 1209
a7812ae4 1210 if (!TCGV_EQUAL(t0, ret)) {
74637406
AJ
1211 tcg_gen_mov_tl(ret, t0);
1212 tcg_temp_free(t0);
79aceca5 1213 }
79aceca5 1214}
74637406
AJ
1215/* Sub functions with Two operands functions */
1216#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
b5a73f8d 1217static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
1218{ \
1219 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1220 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
b5a73f8d 1221 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
1222}
1223/* Sub functions with one operand and one immediate */
1224#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
1225 add_ca, compute_ca, compute_ov) \
b5a73f8d 1226static void glue(gen_, name)(DisasContext *ctx) \
74637406 1227{ \
b5a73f8d 1228 TCGv t0 = tcg_const_tl(const_val); \
74637406
AJ
1229 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1230 cpu_gpr[rA(ctx->opcode)], t0, \
b5a73f8d 1231 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
1232 tcg_temp_free(t0); \
1233}
1234/* subf subf. subfo subfo. */
1235GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1236GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1237/* subfc subfc. subfco subfco. */
1238GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1239GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1240/* subfe subfe. subfeo subfo. */
1241GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1242GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1243/* subfme subfme. subfmeo subfmeo. */
1244GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1245GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1246/* subfze subfze. subfzeo subfzeo.*/
1247GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1248GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
99e300ef 1249
54623277 1250/* subfic */
99e300ef 1251static void gen_subfic(DisasContext *ctx)
79aceca5 1252{
b5a73f8d
RH
1253 TCGv c = tcg_const_tl(SIMM(ctx->opcode));
1254 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1255 c, 0, 1, 0, 0);
1256 tcg_temp_free(c);
79aceca5
FB
1257}
1258
fd3f0081
RH
1259/* neg neg. nego nego. */
1260static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
1261{
1262 TCGv zero = tcg_const_tl(0);
1263 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1264 zero, 0, 0, compute_ov, Rc(ctx->opcode));
1265 tcg_temp_free(zero);
1266}
1267
1268static void gen_neg(DisasContext *ctx)
1269{
1270 gen_op_arith_neg(ctx, 0);
1271}
1272
1273static void gen_nego(DisasContext *ctx)
1274{
1275 gen_op_arith_neg(ctx, 1);
1276}
1277
79aceca5 1278/*** Integer logical ***/
26d67362 1279#define GEN_LOGICAL2(name, tcg_op, opc, type) \
99e300ef 1280static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 1281{ \
26d67362
AJ
1282 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \
1283 cpu_gpr[rB(ctx->opcode)]); \
76a66253 1284 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 1285 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5 1286}
79aceca5 1287
26d67362 1288#define GEN_LOGICAL1(name, tcg_op, opc, type) \
99e300ef 1289static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 1290{ \
26d67362 1291 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \
76a66253 1292 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 1293 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5
FB
1294}
1295
1296/* and & and. */
26d67362 1297GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
79aceca5 1298/* andc & andc. */
26d67362 1299GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
e8eaa2c0 1300
54623277 1301/* andi. */
e8eaa2c0 1302static void gen_andi_(DisasContext *ctx)
79aceca5 1303{
26d67362
AJ
1304 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1305 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1306}
e8eaa2c0 1307
54623277 1308/* andis. */
e8eaa2c0 1309static void gen_andis_(DisasContext *ctx)
79aceca5 1310{
26d67362
AJ
1311 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1312 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1313}
99e300ef 1314
54623277 1315/* cntlzw */
99e300ef 1316static void gen_cntlzw(DisasContext *ctx)
26d67362 1317{
a7812ae4 1318 gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
26d67362 1319 if (unlikely(Rc(ctx->opcode) != 0))
2e31f5d3 1320 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
26d67362 1321}
79aceca5 1322/* eqv & eqv. */
26d67362 1323GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
79aceca5 1324/* extsb & extsb. */
26d67362 1325GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
79aceca5 1326/* extsh & extsh. */
26d67362 1327GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
79aceca5 1328/* nand & nand. */
26d67362 1329GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
79aceca5 1330/* nor & nor. */
26d67362 1331GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
99e300ef 1332
54623277 1333/* or & or. */
99e300ef 1334static void gen_or(DisasContext *ctx)
9a64fbe4 1335{
76a66253
JM
1336 int rs, ra, rb;
1337
1338 rs = rS(ctx->opcode);
1339 ra = rA(ctx->opcode);
1340 rb = rB(ctx->opcode);
1341 /* Optimisation for mr. ri case */
1342 if (rs != ra || rs != rb) {
26d67362
AJ
1343 if (rs != rb)
1344 tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1345 else
1346 tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
76a66253 1347 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1348 gen_set_Rc0(ctx, cpu_gpr[ra]);
76a66253 1349 } else if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 1350 gen_set_Rc0(ctx, cpu_gpr[rs]);
c80f84e3
JM
1351#if defined(TARGET_PPC64)
1352 } else {
26d67362
AJ
1353 int prio = 0;
1354
c80f84e3
JM
1355 switch (rs) {
1356 case 1:
1357 /* Set process priority to low */
26d67362 1358 prio = 2;
c80f84e3
JM
1359 break;
1360 case 6:
1361 /* Set process priority to medium-low */
26d67362 1362 prio = 3;
c80f84e3
JM
1363 break;
1364 case 2:
1365 /* Set process priority to normal */
26d67362 1366 prio = 4;
c80f84e3 1367 break;
be147d08
JM
1368#if !defined(CONFIG_USER_ONLY)
1369 case 31:
76db3ba4 1370 if (ctx->mem_idx > 0) {
be147d08 1371 /* Set process priority to very low */
26d67362 1372 prio = 1;
be147d08
JM
1373 }
1374 break;
1375 case 5:
76db3ba4 1376 if (ctx->mem_idx > 0) {
be147d08 1377 /* Set process priority to medium-hight */
26d67362 1378 prio = 5;
be147d08
JM
1379 }
1380 break;
1381 case 3:
76db3ba4 1382 if (ctx->mem_idx > 0) {
be147d08 1383 /* Set process priority to high */
26d67362 1384 prio = 6;
be147d08
JM
1385 }
1386 break;
be147d08 1387 case 7:
76db3ba4 1388 if (ctx->mem_idx > 1) {
be147d08 1389 /* Set process priority to very high */
26d67362 1390 prio = 7;
be147d08
JM
1391 }
1392 break;
be147d08 1393#endif
c80f84e3
JM
1394 default:
1395 /* nop */
1396 break;
1397 }
26d67362 1398 if (prio) {
a7812ae4 1399 TCGv t0 = tcg_temp_new();
54cdcae6 1400 gen_load_spr(t0, SPR_PPR);
ea363694
AJ
1401 tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1402 tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
54cdcae6 1403 gen_store_spr(SPR_PPR, t0);
ea363694 1404 tcg_temp_free(t0);
26d67362 1405 }
c80f84e3 1406#endif
9a64fbe4 1407 }
9a64fbe4 1408}
79aceca5 1409/* orc & orc. */
26d67362 1410GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
99e300ef 1411
54623277 1412/* xor & xor. */
99e300ef 1413static void gen_xor(DisasContext *ctx)
9a64fbe4 1414{
9a64fbe4 1415 /* Optimisation for "set to zero" case */
26d67362 1416 if (rS(ctx->opcode) != rB(ctx->opcode))
312179c4 1417 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1418 else
1419 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
76a66253 1420 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1421 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
9a64fbe4 1422}
99e300ef 1423
54623277 1424/* ori */
99e300ef 1425static void gen_ori(DisasContext *ctx)
79aceca5 1426{
76a66253 1427 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 1428
9a64fbe4
FB
1429 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1430 /* NOP */
76a66253 1431 /* XXX: should handle special NOPs for POWER series */
9a64fbe4 1432 return;
76a66253 1433 }
26d67362 1434 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5 1435}
99e300ef 1436
54623277 1437/* oris */
99e300ef 1438static void gen_oris(DisasContext *ctx)
79aceca5 1439{
76a66253 1440 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 1441
9a64fbe4
FB
1442 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1443 /* NOP */
1444 return;
76a66253 1445 }
26d67362 1446 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
79aceca5 1447}
99e300ef 1448
54623277 1449/* xori */
99e300ef 1450static void gen_xori(DisasContext *ctx)
79aceca5 1451{
76a66253 1452 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
1453
1454 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1455 /* NOP */
1456 return;
1457 }
26d67362 1458 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5 1459}
99e300ef 1460
54623277 1461/* xoris */
99e300ef 1462static void gen_xoris(DisasContext *ctx)
79aceca5 1463{
76a66253 1464 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
1465
1466 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1467 /* NOP */
1468 return;
1469 }
26d67362 1470 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
79aceca5 1471}
99e300ef 1472
54623277 1473/* popcntb : PowerPC 2.03 specification */
99e300ef 1474static void gen_popcntb(DisasContext *ctx)
d9bce9d9 1475{
eaabeef2
DG
1476 gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1477}
1478
1479static void gen_popcntw(DisasContext *ctx)
1480{
1481 gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1482}
1483
d9bce9d9 1484#if defined(TARGET_PPC64)
eaabeef2
DG
1485/* popcntd: PowerPC 2.06 specification */
1486static void gen_popcntd(DisasContext *ctx)
1487{
1488 gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
d9bce9d9 1489}
eaabeef2 1490#endif
d9bce9d9 1491
725bcec2
AJ
1492/* prtyw: PowerPC 2.05 specification */
1493static void gen_prtyw(DisasContext *ctx)
1494{
1495 TCGv ra = cpu_gpr[rA(ctx->opcode)];
1496 TCGv rs = cpu_gpr[rS(ctx->opcode)];
1497 TCGv t0 = tcg_temp_new();
1498 tcg_gen_shri_tl(t0, rs, 16);
1499 tcg_gen_xor_tl(ra, rs, t0);
1500 tcg_gen_shri_tl(t0, ra, 8);
1501 tcg_gen_xor_tl(ra, ra, t0);
1502 tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL);
1503 tcg_temp_free(t0);
1504}
1505
1506#if defined(TARGET_PPC64)
1507/* prtyd: PowerPC 2.05 specification */
1508static void gen_prtyd(DisasContext *ctx)
1509{
1510 TCGv ra = cpu_gpr[rA(ctx->opcode)];
1511 TCGv rs = cpu_gpr[rS(ctx->opcode)];
1512 TCGv t0 = tcg_temp_new();
1513 tcg_gen_shri_tl(t0, rs, 32);
1514 tcg_gen_xor_tl(ra, rs, t0);
1515 tcg_gen_shri_tl(t0, ra, 16);
1516 tcg_gen_xor_tl(ra, ra, t0);
1517 tcg_gen_shri_tl(t0, ra, 8);
1518 tcg_gen_xor_tl(ra, ra, t0);
1519 tcg_gen_andi_tl(ra, ra, 1);
1520 tcg_temp_free(t0);
1521}
1522#endif
1523
d9bce9d9
JM
1524#if defined(TARGET_PPC64)
1525/* extsw & extsw. */
26d67362 1526GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
99e300ef 1527
54623277 1528/* cntlzd */
99e300ef 1529static void gen_cntlzd(DisasContext *ctx)
26d67362 1530{
a7812ae4 1531 gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
26d67362
AJ
1532 if (unlikely(Rc(ctx->opcode) != 0))
1533 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1534}
d9bce9d9
JM
1535#endif
1536
79aceca5 1537/*** Integer rotate ***/
99e300ef 1538
54623277 1539/* rlwimi & rlwimi. */
99e300ef 1540static void gen_rlwimi(DisasContext *ctx)
79aceca5 1541{
76a66253 1542 uint32_t mb, me, sh;
79aceca5
FB
1543
1544 mb = MB(ctx->opcode);
1545 me = ME(ctx->opcode);
76a66253 1546 sh = SH(ctx->opcode);
d03ef511
AJ
1547 if (likely(sh == 0 && mb == 0 && me == 31)) {
1548 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1549 } else {
d03ef511 1550 target_ulong mask;
a7812ae4
PB
1551 TCGv t1;
1552 TCGv t0 = tcg_temp_new();
54843a58 1553#if defined(TARGET_PPC64)
a7812ae4
PB
1554 TCGv_i32 t2 = tcg_temp_new_i32();
1555 tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
1556 tcg_gen_rotli_i32(t2, t2, sh);
1557 tcg_gen_extu_i32_i64(t0, t2);
1558 tcg_temp_free_i32(t2);
54843a58
AJ
1559#else
1560 tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1561#endif
76a66253 1562#if defined(TARGET_PPC64)
d03ef511
AJ
1563 mb += 32;
1564 me += 32;
76a66253 1565#endif
d03ef511 1566 mask = MASK(mb, me);
a7812ae4 1567 t1 = tcg_temp_new();
d03ef511
AJ
1568 tcg_gen_andi_tl(t0, t0, mask);
1569 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1570 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1571 tcg_temp_free(t0);
1572 tcg_temp_free(t1);
1573 }
76a66253 1574 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1575 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1576}
99e300ef 1577
54623277 1578/* rlwinm & rlwinm. */
99e300ef 1579static void gen_rlwinm(DisasContext *ctx)
79aceca5
FB
1580{
1581 uint32_t mb, me, sh;
3b46e624 1582
79aceca5
FB
1583 sh = SH(ctx->opcode);
1584 mb = MB(ctx->opcode);
1585 me = ME(ctx->opcode);
d03ef511
AJ
1586
1587 if (likely(mb == 0 && me == (31 - sh))) {
1588 if (likely(sh == 0)) {
1589 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1590 } else {
a7812ae4 1591 TCGv t0 = tcg_temp_new();
d03ef511
AJ
1592 tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1593 tcg_gen_shli_tl(t0, t0, sh);
1594 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1595 tcg_temp_free(t0);
79aceca5 1596 }
d03ef511 1597 } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
a7812ae4 1598 TCGv t0 = tcg_temp_new();
d03ef511
AJ
1599 tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1600 tcg_gen_shri_tl(t0, t0, mb);
1601 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1602 tcg_temp_free(t0);
1603 } else {
a7812ae4 1604 TCGv t0 = tcg_temp_new();
54843a58 1605#if defined(TARGET_PPC64)
a7812ae4 1606 TCGv_i32 t1 = tcg_temp_new_i32();
54843a58
AJ
1607 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1608 tcg_gen_rotli_i32(t1, t1, sh);
1609 tcg_gen_extu_i32_i64(t0, t1);
a7812ae4 1610 tcg_temp_free_i32(t1);
54843a58
AJ
1611#else
1612 tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1613#endif
76a66253 1614#if defined(TARGET_PPC64)
d03ef511
AJ
1615 mb += 32;
1616 me += 32;
76a66253 1617#endif
d03ef511
AJ
1618 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1619 tcg_temp_free(t0);
1620 }
76a66253 1621 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1622 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1623}
99e300ef 1624
54623277 1625/* rlwnm & rlwnm. */
99e300ef 1626static void gen_rlwnm(DisasContext *ctx)
79aceca5
FB
1627{
1628 uint32_t mb, me;
54843a58
AJ
1629 TCGv t0;
1630#if defined(TARGET_PPC64)
a7812ae4 1631 TCGv_i32 t1, t2;
54843a58 1632#endif
79aceca5
FB
1633
1634 mb = MB(ctx->opcode);
1635 me = ME(ctx->opcode);
a7812ae4 1636 t0 = tcg_temp_new();
d03ef511 1637 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
54843a58 1638#if defined(TARGET_PPC64)
a7812ae4
PB
1639 t1 = tcg_temp_new_i32();
1640 t2 = tcg_temp_new_i32();
54843a58
AJ
1641 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1642 tcg_gen_trunc_i64_i32(t2, t0);
1643 tcg_gen_rotl_i32(t1, t1, t2);
1644 tcg_gen_extu_i32_i64(t0, t1);
a7812ae4
PB
1645 tcg_temp_free_i32(t1);
1646 tcg_temp_free_i32(t2);
54843a58
AJ
1647#else
1648 tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
1649#endif
76a66253
JM
1650 if (unlikely(mb != 0 || me != 31)) {
1651#if defined(TARGET_PPC64)
1652 mb += 32;
1653 me += 32;
1654#endif
54843a58 1655 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
d03ef511 1656 } else {
54843a58 1657 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
79aceca5 1658 }
54843a58 1659 tcg_temp_free(t0);
76a66253 1660 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1661 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5
FB
1662}
1663
d9bce9d9
JM
1664#if defined(TARGET_PPC64)
1665#define GEN_PPC64_R2(name, opc1, opc2) \
e8eaa2c0 1666static void glue(gen_, name##0)(DisasContext *ctx) \
d9bce9d9
JM
1667{ \
1668 gen_##name(ctx, 0); \
1669} \
e8eaa2c0
BS
1670 \
1671static void glue(gen_, name##1)(DisasContext *ctx) \
d9bce9d9
JM
1672{ \
1673 gen_##name(ctx, 1); \
1674}
1675#define GEN_PPC64_R4(name, opc1, opc2) \
e8eaa2c0 1676static void glue(gen_, name##0)(DisasContext *ctx) \
d9bce9d9
JM
1677{ \
1678 gen_##name(ctx, 0, 0); \
1679} \
e8eaa2c0
BS
1680 \
1681static void glue(gen_, name##1)(DisasContext *ctx) \
d9bce9d9
JM
1682{ \
1683 gen_##name(ctx, 0, 1); \
1684} \
e8eaa2c0
BS
1685 \
1686static void glue(gen_, name##2)(DisasContext *ctx) \
d9bce9d9
JM
1687{ \
1688 gen_##name(ctx, 1, 0); \
1689} \
e8eaa2c0
BS
1690 \
1691static void glue(gen_, name##3)(DisasContext *ctx) \
d9bce9d9
JM
1692{ \
1693 gen_##name(ctx, 1, 1); \
1694}
51789c41 1695
636aa200
BS
1696static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
1697 uint32_t sh)
51789c41 1698{
d03ef511
AJ
1699 if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
1700 tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1701 } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
1702 tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
1703 } else {
a7812ae4 1704 TCGv t0 = tcg_temp_new();
54843a58 1705 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
d03ef511 1706 if (likely(mb == 0 && me == 63)) {
54843a58 1707 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
d03ef511
AJ
1708 } else {
1709 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
51789c41 1710 }
d03ef511 1711 tcg_temp_free(t0);
51789c41 1712 }
51789c41 1713 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1714 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
51789c41 1715}
d9bce9d9 1716/* rldicl - rldicl. */
636aa200 1717static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
d9bce9d9 1718{
51789c41 1719 uint32_t sh, mb;
d9bce9d9 1720
9d53c753
JM
1721 sh = SH(ctx->opcode) | (shn << 5);
1722 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 1723 gen_rldinm(ctx, mb, 63, sh);
d9bce9d9 1724}
51789c41 1725GEN_PPC64_R4(rldicl, 0x1E, 0x00);
d9bce9d9 1726/* rldicr - rldicr. */
636aa200 1727static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
d9bce9d9 1728{
51789c41 1729 uint32_t sh, me;
d9bce9d9 1730
9d53c753
JM
1731 sh = SH(ctx->opcode) | (shn << 5);
1732 me = MB(ctx->opcode) | (men << 5);
51789c41 1733 gen_rldinm(ctx, 0, me, sh);
d9bce9d9 1734}
51789c41 1735GEN_PPC64_R4(rldicr, 0x1E, 0x02);
d9bce9d9 1736/* rldic - rldic. */
636aa200 1737static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
d9bce9d9 1738{
51789c41 1739 uint32_t sh, mb;
d9bce9d9 1740
9d53c753
JM
1741 sh = SH(ctx->opcode) | (shn << 5);
1742 mb = MB(ctx->opcode) | (mbn << 5);
51789c41
JM
1743 gen_rldinm(ctx, mb, 63 - sh, sh);
1744}
1745GEN_PPC64_R4(rldic, 0x1E, 0x04);
1746
636aa200 1747static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
51789c41 1748{
54843a58 1749 TCGv t0;
d03ef511 1750
a7812ae4 1751 t0 = tcg_temp_new();
d03ef511 1752 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
54843a58 1753 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
51789c41 1754 if (unlikely(mb != 0 || me != 63)) {
54843a58
AJ
1755 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1756 } else {
1757 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1758 }
1759 tcg_temp_free(t0);
51789c41 1760 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1761 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
d9bce9d9 1762}
51789c41 1763
d9bce9d9 1764/* rldcl - rldcl. */
636aa200 1765static inline void gen_rldcl(DisasContext *ctx, int mbn)
d9bce9d9 1766{
51789c41 1767 uint32_t mb;
d9bce9d9 1768
9d53c753 1769 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 1770 gen_rldnm(ctx, mb, 63);
d9bce9d9 1771}
36081602 1772GEN_PPC64_R2(rldcl, 0x1E, 0x08);
d9bce9d9 1773/* rldcr - rldcr. */
636aa200 1774static inline void gen_rldcr(DisasContext *ctx, int men)
d9bce9d9 1775{
51789c41 1776 uint32_t me;
d9bce9d9 1777
9d53c753 1778 me = MB(ctx->opcode) | (men << 5);
51789c41 1779 gen_rldnm(ctx, 0, me);
d9bce9d9 1780}
36081602 1781GEN_PPC64_R2(rldcr, 0x1E, 0x09);
d9bce9d9 1782/* rldimi - rldimi. */
636aa200 1783static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
d9bce9d9 1784{
271a916e 1785 uint32_t sh, mb, me;
d9bce9d9 1786
9d53c753
JM
1787 sh = SH(ctx->opcode) | (shn << 5);
1788 mb = MB(ctx->opcode) | (mbn << 5);
271a916e 1789 me = 63 - sh;
d03ef511
AJ
1790 if (unlikely(sh == 0 && mb == 0)) {
1791 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1792 } else {
1793 TCGv t0, t1;
1794 target_ulong mask;
1795
a7812ae4 1796 t0 = tcg_temp_new();
54843a58 1797 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
a7812ae4 1798 t1 = tcg_temp_new();
d03ef511
AJ
1799 mask = MASK(mb, me);
1800 tcg_gen_andi_tl(t0, t0, mask);
1801 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1802 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1803 tcg_temp_free(t0);
1804 tcg_temp_free(t1);
51789c41 1805 }
51789c41 1806 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1807 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
d9bce9d9 1808}
36081602 1809GEN_PPC64_R4(rldimi, 0x1E, 0x06);
d9bce9d9
JM
1810#endif
1811
79aceca5 1812/*** Integer shift ***/
99e300ef 1813
54623277 1814/* slw & slw. */
99e300ef 1815static void gen_slw(DisasContext *ctx)
26d67362 1816{
7fd6bf7d 1817 TCGv t0, t1;
26d67362 1818
7fd6bf7d
AJ
1819 t0 = tcg_temp_new();
1820 /* AND rS with a mask that is 0 when rB >= 0x20 */
1821#if defined(TARGET_PPC64)
1822 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1823 tcg_gen_sari_tl(t0, t0, 0x3f);
1824#else
1825 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1826 tcg_gen_sari_tl(t0, t0, 0x1f);
1827#endif
1828 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1829 t1 = tcg_temp_new();
1830 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1831 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1832 tcg_temp_free(t1);
fea0c503 1833 tcg_temp_free(t0);
7fd6bf7d 1834 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
26d67362
AJ
1835 if (unlikely(Rc(ctx->opcode) != 0))
1836 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1837}
99e300ef 1838
54623277 1839/* sraw & sraw. */
99e300ef 1840static void gen_sraw(DisasContext *ctx)
26d67362 1841{
d15f74fb 1842 gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
a7812ae4 1843 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1844 if (unlikely(Rc(ctx->opcode) != 0))
1845 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1846}
99e300ef 1847
54623277 1848/* srawi & srawi. */
99e300ef 1849static void gen_srawi(DisasContext *ctx)
79aceca5 1850{
26d67362 1851 int sh = SH(ctx->opcode);
ba4af3e4
RH
1852 TCGv dst = cpu_gpr[rA(ctx->opcode)];
1853 TCGv src = cpu_gpr[rS(ctx->opcode)];
1854 if (sh == 0) {
1855 tcg_gen_mov_tl(dst, src);
da91a00f 1856 tcg_gen_movi_tl(cpu_ca, 0);
26d67362 1857 } else {
ba4af3e4
RH
1858 TCGv t0;
1859 tcg_gen_ext32s_tl(dst, src);
1860 tcg_gen_andi_tl(cpu_ca, dst, (1ULL << sh) - 1);
1861 t0 = tcg_temp_new();
1862 tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1);
1863 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
1864 tcg_temp_free(t0);
1865 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
1866 tcg_gen_sari_tl(dst, dst, sh);
1867 }
1868 if (unlikely(Rc(ctx->opcode) != 0)) {
1869 gen_set_Rc0(ctx, dst);
d9bce9d9 1870 }
79aceca5 1871}
99e300ef 1872
54623277 1873/* srw & srw. */
99e300ef 1874static void gen_srw(DisasContext *ctx)
26d67362 1875{
fea0c503 1876 TCGv t0, t1;
d9bce9d9 1877
7fd6bf7d
AJ
1878 t0 = tcg_temp_new();
1879 /* AND rS with a mask that is 0 when rB >= 0x20 */
1880#if defined(TARGET_PPC64)
1881 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1882 tcg_gen_sari_tl(t0, t0, 0x3f);
1883#else
1884 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1885 tcg_gen_sari_tl(t0, t0, 0x1f);
1886#endif
1887 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1888 tcg_gen_ext32u_tl(t0, t0);
a7812ae4 1889 t1 = tcg_temp_new();
7fd6bf7d
AJ
1890 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1891 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
fea0c503 1892 tcg_temp_free(t1);
fea0c503 1893 tcg_temp_free(t0);
26d67362
AJ
1894 if (unlikely(Rc(ctx->opcode) != 0))
1895 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1896}
54623277 1897
d9bce9d9
JM
1898#if defined(TARGET_PPC64)
1899/* sld & sld. */
99e300ef 1900static void gen_sld(DisasContext *ctx)
26d67362 1901{
7fd6bf7d 1902 TCGv t0, t1;
26d67362 1903
7fd6bf7d
AJ
1904 t0 = tcg_temp_new();
1905 /* AND rS with a mask that is 0 when rB >= 0x40 */
1906 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1907 tcg_gen_sari_tl(t0, t0, 0x3f);
1908 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1909 t1 = tcg_temp_new();
1910 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
1911 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1912 tcg_temp_free(t1);
fea0c503 1913 tcg_temp_free(t0);
26d67362
AJ
1914 if (unlikely(Rc(ctx->opcode) != 0))
1915 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1916}
99e300ef 1917
54623277 1918/* srad & srad. */
99e300ef 1919static void gen_srad(DisasContext *ctx)
26d67362 1920{
d15f74fb 1921 gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
a7812ae4 1922 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1923 if (unlikely(Rc(ctx->opcode) != 0))
1924 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1925}
d9bce9d9 1926/* sradi & sradi. */
636aa200 1927static inline void gen_sradi(DisasContext *ctx, int n)
d9bce9d9 1928{
26d67362 1929 int sh = SH(ctx->opcode) + (n << 5);
ba4af3e4
RH
1930 TCGv dst = cpu_gpr[rA(ctx->opcode)];
1931 TCGv src = cpu_gpr[rS(ctx->opcode)];
1932 if (sh == 0) {
1933 tcg_gen_mov_tl(dst, src);
da91a00f 1934 tcg_gen_movi_tl(cpu_ca, 0);
26d67362 1935 } else {
ba4af3e4
RH
1936 TCGv t0;
1937 tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
1938 t0 = tcg_temp_new();
1939 tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1);
1940 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
1941 tcg_temp_free(t0);
1942 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
1943 tcg_gen_sari_tl(dst, src, sh);
1944 }
1945 if (unlikely(Rc(ctx->opcode) != 0)) {
1946 gen_set_Rc0(ctx, dst);
d9bce9d9 1947 }
d9bce9d9 1948}
e8eaa2c0
BS
1949
1950static void gen_sradi0(DisasContext *ctx)
d9bce9d9
JM
1951{
1952 gen_sradi(ctx, 0);
1953}
e8eaa2c0
BS
1954
1955static void gen_sradi1(DisasContext *ctx)
d9bce9d9
JM
1956{
1957 gen_sradi(ctx, 1);
1958}
99e300ef 1959
54623277 1960/* srd & srd. */
99e300ef 1961static void gen_srd(DisasContext *ctx)
26d67362 1962{
7fd6bf7d 1963 TCGv t0, t1;
26d67362 1964
7fd6bf7d
AJ
1965 t0 = tcg_temp_new();
1966 /* AND rS with a mask that is 0 when rB >= 0x40 */
1967 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1968 tcg_gen_sari_tl(t0, t0, 0x3f);
1969 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1970 t1 = tcg_temp_new();
1971 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
1972 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1973 tcg_temp_free(t1);
fea0c503 1974 tcg_temp_free(t0);
26d67362
AJ
1975 if (unlikely(Rc(ctx->opcode) != 0))
1976 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1977}
d9bce9d9 1978#endif
79aceca5
FB
1979
1980/*** Floating-Point arithmetic ***/
7c58044c 1981#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
99e300ef 1982static void gen_f##name(DisasContext *ctx) \
9a64fbe4 1983{ \
76a66253 1984 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 1985 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
1986 return; \
1987 } \
eb44b959
AJ
1988 /* NIP cannot be restored if the memory exception comes from an helper */ \
1989 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 1990 gen_reset_fpstatus(); \
8e703949
BS
1991 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
1992 cpu_fpr[rA(ctx->opcode)], \
af12906f 1993 cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
4ecc3190 1994 if (isfloat) { \
8e703949
BS
1995 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
1996 cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 1997 } \
af12906f
AJ
1998 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf, \
1999 Rc(ctx->opcode) != 0); \
9a64fbe4
FB
2000}
2001
7c58044c
JM
2002#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
2003_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
2004_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
9a64fbe4 2005
7c58044c 2006#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
99e300ef 2007static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2008{ \
76a66253 2009 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2010 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2011 return; \
2012 } \
eb44b959
AJ
2013 /* NIP cannot be restored if the memory exception comes from an helper */ \
2014 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2015 gen_reset_fpstatus(); \
8e703949
BS
2016 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2017 cpu_fpr[rA(ctx->opcode)], \
af12906f 2018 cpu_fpr[rB(ctx->opcode)]); \
4ecc3190 2019 if (isfloat) { \
8e703949
BS
2020 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2021 cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2022 } \
af12906f
AJ
2023 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2024 set_fprf, Rc(ctx->opcode) != 0); \
9a64fbe4 2025}
7c58044c
JM
2026#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
2027_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2028_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
9a64fbe4 2029
7c58044c 2030#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
99e300ef 2031static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2032{ \
76a66253 2033 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2034 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2035 return; \
2036 } \
eb44b959
AJ
2037 /* NIP cannot be restored if the memory exception comes from an helper */ \
2038 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2039 gen_reset_fpstatus(); \
8e703949
BS
2040 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2041 cpu_fpr[rA(ctx->opcode)], \
2042 cpu_fpr[rC(ctx->opcode)]); \
4ecc3190 2043 if (isfloat) { \
8e703949
BS
2044 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2045 cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2046 } \
af12906f
AJ
2047 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2048 set_fprf, Rc(ctx->opcode) != 0); \
9a64fbe4 2049}
7c58044c
JM
2050#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
2051_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2052_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
9a64fbe4 2053
7c58044c 2054#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
99e300ef 2055static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2056{ \
76a66253 2057 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2058 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2059 return; \
2060 } \
eb44b959
AJ
2061 /* NIP cannot be restored if the memory exception comes from an helper */ \
2062 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2063 gen_reset_fpstatus(); \
8e703949
BS
2064 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2065 cpu_fpr[rB(ctx->opcode)]); \
af12906f
AJ
2066 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2067 set_fprf, Rc(ctx->opcode) != 0); \
79aceca5
FB
2068}
2069
7c58044c 2070#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
99e300ef 2071static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2072{ \
76a66253 2073 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2074 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2075 return; \
2076 } \
eb44b959
AJ
2077 /* NIP cannot be restored if the memory exception comes from an helper */ \
2078 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2079 gen_reset_fpstatus(); \
8e703949
BS
2080 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
2081 cpu_fpr[rB(ctx->opcode)]); \
af12906f
AJ
2082 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2083 set_fprf, Rc(ctx->opcode) != 0); \
79aceca5
FB
2084}
2085
9a64fbe4 2086/* fadd - fadds */
7c58044c 2087GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
4ecc3190 2088/* fdiv - fdivs */
7c58044c 2089GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
4ecc3190 2090/* fmul - fmuls */
7c58044c 2091GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
79aceca5 2092
d7e4b87e 2093/* fre */
7c58044c 2094GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
d7e4b87e 2095
a750fc0b 2096/* fres */
7c58044c 2097GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
79aceca5 2098
a750fc0b 2099/* frsqrte */
7c58044c
JM
2100GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2101
2102/* frsqrtes */
99e300ef 2103static void gen_frsqrtes(DisasContext *ctx)
7c58044c 2104{
af12906f 2105 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2106 gen_exception(ctx, POWERPC_EXCP_FPU);
af12906f
AJ
2107 return;
2108 }
eb44b959
AJ
2109 /* NIP cannot be restored if the memory exception comes from an helper */
2110 gen_update_nip(ctx, ctx->nip - 4);
af12906f 2111 gen_reset_fpstatus();
8e703949
BS
2112 gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
2113 cpu_fpr[rB(ctx->opcode)]);
2114 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
2115 cpu_fpr[rD(ctx->opcode)]);
af12906f 2116 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
7c58044c 2117}
79aceca5 2118
a750fc0b 2119/* fsel */
7c58044c 2120_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
4ecc3190 2121/* fsub - fsubs */
7c58044c 2122GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
79aceca5 2123/* Optional: */
99e300ef 2124
54623277 2125/* fsqrt */
99e300ef 2126static void gen_fsqrt(DisasContext *ctx)
c7d344af 2127{
76a66253 2128 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2129 gen_exception(ctx, POWERPC_EXCP_FPU);
c7d344af
FB
2130 return;
2131 }
eb44b959
AJ
2132 /* NIP cannot be restored if the memory exception comes from an helper */
2133 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2134 gen_reset_fpstatus();
8e703949
BS
2135 gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
2136 cpu_fpr[rB(ctx->opcode)]);
af12906f 2137 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
c7d344af 2138}
79aceca5 2139
99e300ef 2140static void gen_fsqrts(DisasContext *ctx)
79aceca5 2141{
76a66253 2142 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2143 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2144 return;
2145 }
eb44b959
AJ
2146 /* NIP cannot be restored if the memory exception comes from an helper */
2147 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2148 gen_reset_fpstatus();
8e703949
BS
2149 gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
2150 cpu_fpr[rB(ctx->opcode)]);
2151 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
2152 cpu_fpr[rD(ctx->opcode)]);
af12906f 2153 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
79aceca5
FB
2154}
2155
2156/*** Floating-Point multiply-and-add ***/
4ecc3190 2157/* fmadd - fmadds */
7c58044c 2158GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
4ecc3190 2159/* fmsub - fmsubs */
7c58044c 2160GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
4ecc3190 2161/* fnmadd - fnmadds */
7c58044c 2162GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
4ecc3190 2163/* fnmsub - fnmsubs */
7c58044c 2164GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
79aceca5
FB
2165
2166/*** Floating-Point round & convert ***/
2167/* fctiw */
7c58044c 2168GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
79aceca5 2169/* fctiwz */
7c58044c 2170GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
79aceca5 2171/* frsp */
7c58044c 2172GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
426613db
JM
2173#if defined(TARGET_PPC64)
2174/* fcfid */
7c58044c 2175GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
426613db 2176/* fctid */
7c58044c 2177GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
426613db 2178/* fctidz */
7c58044c 2179GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
426613db 2180#endif
79aceca5 2181
d7e4b87e 2182/* frin */
7c58044c 2183GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
d7e4b87e 2184/* friz */
7c58044c 2185GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
d7e4b87e 2186/* frip */
7c58044c 2187GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
d7e4b87e 2188/* frim */
7c58044c 2189GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
d7e4b87e 2190
79aceca5 2191/*** Floating-Point compare ***/
99e300ef 2192
54623277 2193/* fcmpo */
99e300ef 2194static void gen_fcmpo(DisasContext *ctx)
79aceca5 2195{
330c483b 2196 TCGv_i32 crf;
76a66253 2197 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2198 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2199 return;
2200 }
eb44b959
AJ
2201 /* NIP cannot be restored if the memory exception comes from an helper */
2202 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2203 gen_reset_fpstatus();
9a819377 2204 crf = tcg_const_i32(crfD(ctx->opcode));
8e703949
BS
2205 gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
2206 cpu_fpr[rB(ctx->opcode)], crf);
330c483b 2207 tcg_temp_free_i32(crf);
8e703949 2208 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2209}
2210
2211/* fcmpu */
99e300ef 2212static void gen_fcmpu(DisasContext *ctx)
79aceca5 2213{
330c483b 2214 TCGv_i32 crf;
76a66253 2215 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2216 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2217 return;
2218 }
eb44b959
AJ
2219 /* NIP cannot be restored if the memory exception comes from an helper */
2220 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2221 gen_reset_fpstatus();
9a819377 2222 crf = tcg_const_i32(crfD(ctx->opcode));
8e703949
BS
2223 gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
2224 cpu_fpr[rB(ctx->opcode)], crf);
330c483b 2225 tcg_temp_free_i32(crf);
8e703949 2226 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2227}
2228
9a64fbe4
FB
2229/*** Floating-point move ***/
2230/* fabs */
7c58044c 2231/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
bf45a2e6
AJ
2232static void gen_fabs(DisasContext *ctx)
2233{
2234 if (unlikely(!ctx->fpu_enabled)) {
2235 gen_exception(ctx, POWERPC_EXCP_FPU);
2236 return;
2237 }
2238 tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2239 ~(1ULL << 63));
2240 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2241}
9a64fbe4
FB
2242
2243/* fmr - fmr. */
7c58044c 2244/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
99e300ef 2245static void gen_fmr(DisasContext *ctx)
9a64fbe4 2246{
76a66253 2247 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2248 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2249 return;
2250 }
af12906f
AJ
2251 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2252 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
9a64fbe4
FB
2253}
2254
2255/* fnabs */
7c58044c 2256/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
bf45a2e6
AJ
2257static void gen_fnabs(DisasContext *ctx)
2258{
2259 if (unlikely(!ctx->fpu_enabled)) {
2260 gen_exception(ctx, POWERPC_EXCP_FPU);
2261 return;
2262 }
2263 tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2264 1ULL << 63);
2265 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2266}
2267
9a64fbe4 2268/* fneg */
7c58044c 2269/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
bf45a2e6
AJ
2270static void gen_fneg(DisasContext *ctx)
2271{
2272 if (unlikely(!ctx->fpu_enabled)) {
2273 gen_exception(ctx, POWERPC_EXCP_FPU);
2274 return;
2275 }
2276 tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
2277 1ULL << 63);
2278 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2279}
9a64fbe4 2280
f0332888
AJ
2281/* fcpsgn: PowerPC 2.05 specification */
2282/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
2283static void gen_fcpsgn(DisasContext *ctx)
2284{
2285 if (unlikely(!ctx->fpu_enabled)) {
2286 gen_exception(ctx, POWERPC_EXCP_FPU);
2287 return;
2288 }
2289 tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
2290 cpu_fpr[rB(ctx->opcode)], 0, 63);
2291 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
2292}
2293
79aceca5 2294/*** Floating-Point status & ctrl register ***/
99e300ef 2295
54623277 2296/* mcrfs */
99e300ef 2297static void gen_mcrfs(DisasContext *ctx)
79aceca5 2298{
30304420 2299 TCGv tmp = tcg_temp_new();
7c58044c
JM
2300 int bfa;
2301
76a66253 2302 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2303 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2304 return;
2305 }
7c58044c 2306 bfa = 4 * (7 - crfS(ctx->opcode));
30304420
DG
2307 tcg_gen_shri_tl(tmp, cpu_fpscr, bfa);
2308 tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
2309 tcg_temp_free(tmp);
e1571908 2310 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
30304420 2311 tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
79aceca5
FB
2312}
2313
2314/* mffs */
99e300ef 2315static void gen_mffs(DisasContext *ctx)
79aceca5 2316{
76a66253 2317 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2318 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2319 return;
2320 }
7c58044c 2321 gen_reset_fpstatus();
30304420 2322 tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
af12906f 2323 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
79aceca5
FB
2324}
2325
2326/* mtfsb0 */
99e300ef 2327static void gen_mtfsb0(DisasContext *ctx)
79aceca5 2328{
fb0eaffc 2329 uint8_t crb;
3b46e624 2330
76a66253 2331 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2332 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2333 return;
2334 }
6e35d524 2335 crb = 31 - crbD(ctx->opcode);
7c58044c 2336 gen_reset_fpstatus();
6e35d524 2337 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
eb44b959
AJ
2338 TCGv_i32 t0;
2339 /* NIP cannot be restored if the memory exception comes from an helper */
2340 gen_update_nip(ctx, ctx->nip - 4);
2341 t0 = tcg_const_i32(crb);
8e703949 2342 gen_helper_fpscr_clrbit(cpu_env, t0);
6e35d524
AJ
2343 tcg_temp_free_i32(t0);
2344 }
7c58044c 2345 if (unlikely(Rc(ctx->opcode) != 0)) {
30304420
DG
2346 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2347 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
7c58044c 2348 }
79aceca5
FB
2349}
2350
2351/* mtfsb1 */
99e300ef 2352static void gen_mtfsb1(DisasContext *ctx)
79aceca5 2353{
fb0eaffc 2354 uint8_t crb;
3b46e624 2355
76a66253 2356 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2357 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2358 return;
2359 }
6e35d524 2360 crb = 31 - crbD(ctx->opcode);
7c58044c
JM
2361 gen_reset_fpstatus();
2362 /* XXX: we pretend we can only do IEEE floating-point computations */
af12906f 2363 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
eb44b959
AJ
2364 TCGv_i32 t0;
2365 /* NIP cannot be restored if the memory exception comes from an helper */
2366 gen_update_nip(ctx, ctx->nip - 4);
2367 t0 = tcg_const_i32(crb);
8e703949 2368 gen_helper_fpscr_setbit(cpu_env, t0);
0f2f39c2 2369 tcg_temp_free_i32(t0);
af12906f 2370 }
7c58044c 2371 if (unlikely(Rc(ctx->opcode) != 0)) {
30304420
DG
2372 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2373 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
7c58044c
JM
2374 }
2375 /* We can raise a differed exception */
8e703949 2376 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2377}
2378
2379/* mtfsf */
99e300ef 2380static void gen_mtfsf(DisasContext *ctx)
79aceca5 2381{
0f2f39c2 2382 TCGv_i32 t0;
7d08d856 2383 int flm, l, w;
af12906f 2384
76a66253 2385 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2386 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2387 return;
2388 }
7d08d856
AJ
2389 flm = FPFLM(ctx->opcode);
2390 l = FPL(ctx->opcode);
2391 w = FPW(ctx->opcode);
2392 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
2393 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2394 return;
2395 }
eb44b959
AJ
2396 /* NIP cannot be restored if the memory exception comes from an helper */
2397 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2398 gen_reset_fpstatus();
7d08d856
AJ
2399 if (l) {
2400 t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
2401 } else {
2402 t0 = tcg_const_i32(flm << (w * 8));
2403 }
8e703949 2404 gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
0f2f39c2 2405 tcg_temp_free_i32(t0);
7c58044c 2406 if (unlikely(Rc(ctx->opcode) != 0)) {
30304420
DG
2407 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2408 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
7c58044c
JM
2409 }
2410 /* We can raise a differed exception */
8e703949 2411 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2412}
2413
2414/* mtfsfi */
99e300ef 2415static void gen_mtfsfi(DisasContext *ctx)
79aceca5 2416{
7d08d856 2417 int bf, sh, w;
0f2f39c2
AJ
2418 TCGv_i64 t0;
2419 TCGv_i32 t1;
7c58044c 2420
76a66253 2421 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2422 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2423 return;
2424 }
7d08d856
AJ
2425 w = FPW(ctx->opcode);
2426 bf = FPBF(ctx->opcode);
2427 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
2428 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
2429 return;
2430 }
2431 sh = (8 * w) + 7 - bf;
eb44b959
AJ
2432 /* NIP cannot be restored if the memory exception comes from an helper */
2433 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2434 gen_reset_fpstatus();
7d08d856 2435 t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
af12906f 2436 t1 = tcg_const_i32(1 << sh);
8e703949 2437 gen_helper_store_fpscr(cpu_env, t0, t1);
0f2f39c2
AJ
2438 tcg_temp_free_i64(t0);
2439 tcg_temp_free_i32(t1);
7c58044c 2440 if (unlikely(Rc(ctx->opcode) != 0)) {
30304420
DG
2441 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
2442 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
7c58044c
JM
2443 }
2444 /* We can raise a differed exception */
8e703949 2445 gen_helper_float_check_status(cpu_env);
79aceca5
FB
2446}
2447
76a66253
JM
2448/*** Addressing modes ***/
2449/* Register indirect with immediate index : EA = (rA|0) + SIMM */
636aa200
BS
2450static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
2451 target_long maskl)
76a66253
JM
2452{
2453 target_long simm = SIMM(ctx->opcode);
2454
be147d08 2455 simm &= ~maskl;
76db3ba4 2456 if (rA(ctx->opcode) == 0) {
c791fe84
RH
2457 if (NARROW_MODE(ctx)) {
2458 simm = (uint32_t)simm;
2459 }
e2be8d8d 2460 tcg_gen_movi_tl(EA, simm);
76db3ba4 2461 } else if (likely(simm != 0)) {
e2be8d8d 2462 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
c791fe84 2463 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
2464 tcg_gen_ext32u_tl(EA, EA);
2465 }
76db3ba4 2466 } else {
c791fe84 2467 if (NARROW_MODE(ctx)) {
76db3ba4 2468 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
c791fe84
RH
2469 } else {
2470 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2471 }
76db3ba4 2472 }
76a66253
JM
2473}
2474
636aa200 2475static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
76a66253 2476{
76db3ba4 2477 if (rA(ctx->opcode) == 0) {
c791fe84 2478 if (NARROW_MODE(ctx)) {
76db3ba4 2479 tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
c791fe84
RH
2480 } else {
2481 tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2482 }
76db3ba4 2483 } else {
e2be8d8d 2484 tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
c791fe84 2485 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
2486 tcg_gen_ext32u_tl(EA, EA);
2487 }
76db3ba4 2488 }
76a66253
JM
2489}
2490
636aa200 2491static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
76a66253 2492{
76db3ba4 2493 if (rA(ctx->opcode) == 0) {
e2be8d8d 2494 tcg_gen_movi_tl(EA, 0);
c791fe84
RH
2495 } else if (NARROW_MODE(ctx)) {
2496 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
76db3ba4 2497 } else {
c791fe84 2498 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
76db3ba4
AJ
2499 }
2500}
2501
636aa200
BS
2502static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
2503 target_long val)
76db3ba4
AJ
2504{
2505 tcg_gen_addi_tl(ret, arg1, val);
c791fe84 2506 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
2507 tcg_gen_ext32u_tl(ret, ret);
2508 }
76a66253
JM
2509}
2510
636aa200 2511static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
cf360a32
AJ
2512{
2513 int l1 = gen_new_label();
2514 TCGv t0 = tcg_temp_new();
2515 TCGv_i32 t1, t2;
2516 /* NIP cannot be restored if the memory exception comes from an helper */
2517 gen_update_nip(ctx, ctx->nip - 4);
2518 tcg_gen_andi_tl(t0, EA, mask);
2519 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2520 t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2521 t2 = tcg_const_i32(0);
e5f17ac6 2522 gen_helper_raise_exception_err(cpu_env, t1, t2);
cf360a32
AJ
2523 tcg_temp_free_i32(t1);
2524 tcg_temp_free_i32(t2);
2525 gen_set_label(l1);
2526 tcg_temp_free(t0);
2527}
2528
7863667f 2529/*** Integer load ***/
636aa200 2530static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
76db3ba4
AJ
2531{
2532 tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2533}
2534
636aa200 2535static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
76db3ba4
AJ
2536{
2537 tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
2538}
2539
636aa200 2540static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
76db3ba4
AJ
2541{
2542 tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2543 if (unlikely(ctx->le_mode)) {
fa3966a3 2544 tcg_gen_bswap16_tl(arg1, arg1);
76db3ba4 2545 }
b61f2753
AJ
2546}
2547
636aa200 2548static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2549{
76db3ba4 2550 if (unlikely(ctx->le_mode)) {
76db3ba4 2551 tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
fa3966a3 2552 tcg_gen_bswap16_tl(arg1, arg1);
76db3ba4 2553 tcg_gen_ext16s_tl(arg1, arg1);
76db3ba4
AJ
2554 } else {
2555 tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
2556 }
b61f2753
AJ
2557}
2558
636aa200 2559static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2560{
76db3ba4
AJ
2561 tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2562 if (unlikely(ctx->le_mode)) {
fa3966a3 2563 tcg_gen_bswap32_tl(arg1, arg1);
76db3ba4 2564 }
b61f2753
AJ
2565}
2566
636aa200 2567static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2568{
a457e7ee 2569 if (unlikely(ctx->le_mode)) {
76db3ba4 2570 tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
fa3966a3
AJ
2571 tcg_gen_bswap32_tl(arg1, arg1);
2572 tcg_gen_ext32s_tl(arg1, arg1);
b61f2753 2573 } else
76db3ba4 2574 tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
b61f2753
AJ
2575}
2576
636aa200 2577static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
b61f2753 2578{
76db3ba4
AJ
2579 tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
2580 if (unlikely(ctx->le_mode)) {
66896cb8 2581 tcg_gen_bswap64_i64(arg1, arg1);
76db3ba4 2582 }
b61f2753
AJ
2583}
2584
636aa200 2585static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2586{
76db3ba4 2587 tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
b61f2753
AJ
2588}
2589
636aa200 2590static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2591{
76db3ba4 2592 if (unlikely(ctx->le_mode)) {
76db3ba4
AJ
2593 TCGv t0 = tcg_temp_new();
2594 tcg_gen_ext16u_tl(t0, arg1);
fa3966a3 2595 tcg_gen_bswap16_tl(t0, t0);
76db3ba4
AJ
2596 tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2597 tcg_temp_free(t0);
76db3ba4
AJ
2598 } else {
2599 tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2600 }
b61f2753
AJ
2601}
2602
636aa200 2603static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2604{
76db3ba4 2605 if (unlikely(ctx->le_mode)) {
fa3966a3
AJ
2606 TCGv t0 = tcg_temp_new();
2607 tcg_gen_ext32u_tl(t0, arg1);
2608 tcg_gen_bswap32_tl(t0, t0);
76db3ba4
AJ
2609 tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2610 tcg_temp_free(t0);
76db3ba4
AJ
2611 } else {
2612 tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2613 }
b61f2753
AJ
2614}
2615
636aa200 2616static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
b61f2753 2617{
76db3ba4 2618 if (unlikely(ctx->le_mode)) {
a7812ae4 2619 TCGv_i64 t0 = tcg_temp_new_i64();
66896cb8 2620 tcg_gen_bswap64_i64(t0, arg1);
76db3ba4 2621 tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
a7812ae4 2622 tcg_temp_free_i64(t0);
b61f2753 2623 } else
76db3ba4 2624 tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
b61f2753
AJ
2625}
2626
0c8aacd4 2627#define GEN_LD(name, ldop, opc, type) \
99e300ef 2628static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 2629{ \
76db3ba4
AJ
2630 TCGv EA; \
2631 gen_set_access_type(ctx, ACCESS_INT); \
2632 EA = tcg_temp_new(); \
2633 gen_addr_imm_index(ctx, EA, 0); \
2634 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753 2635 tcg_temp_free(EA); \
79aceca5
FB
2636}
2637
0c8aacd4 2638#define GEN_LDU(name, ldop, opc, type) \
99e300ef 2639static void glue(gen_, name##u)(DisasContext *ctx) \
79aceca5 2640{ \
b61f2753 2641 TCGv EA; \
76a66253
JM
2642 if (unlikely(rA(ctx->opcode) == 0 || \
2643 rA(ctx->opcode) == rD(ctx->opcode))) { \
e06fcd75 2644 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2645 return; \
9a64fbe4 2646 } \
76db3ba4 2647 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2648 EA = tcg_temp_new(); \
9d53c753 2649 if (type == PPC_64B) \
76db3ba4 2650 gen_addr_imm_index(ctx, EA, 0x03); \
9d53c753 2651 else \
76db3ba4
AJ
2652 gen_addr_imm_index(ctx, EA, 0); \
2653 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753
AJ
2654 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2655 tcg_temp_free(EA); \
79aceca5
FB
2656}
2657
0c8aacd4 2658#define GEN_LDUX(name, ldop, opc2, opc3, type) \
99e300ef 2659static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 2660{ \
b61f2753 2661 TCGv EA; \
76a66253
JM
2662 if (unlikely(rA(ctx->opcode) == 0 || \
2663 rA(ctx->opcode) == rD(ctx->opcode))) { \
e06fcd75 2664 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2665 return; \
9a64fbe4 2666 } \
76db3ba4 2667 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2668 EA = tcg_temp_new(); \
76db3ba4
AJ
2669 gen_addr_reg_index(ctx, EA); \
2670 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753
AJ
2671 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2672 tcg_temp_free(EA); \
79aceca5
FB
2673}
2674
cd6e9320 2675#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
99e300ef 2676static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 2677{ \
76db3ba4
AJ
2678 TCGv EA; \
2679 gen_set_access_type(ctx, ACCESS_INT); \
2680 EA = tcg_temp_new(); \
2681 gen_addr_reg_index(ctx, EA); \
2682 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753 2683 tcg_temp_free(EA); \
79aceca5 2684}
cd6e9320
TH
2685#define GEN_LDX(name, ldop, opc2, opc3, type) \
2686 GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
79aceca5 2687
0c8aacd4
AJ
2688#define GEN_LDS(name, ldop, op, type) \
2689GEN_LD(name, ldop, op | 0x20, type); \
2690GEN_LDU(name, ldop, op | 0x21, type); \
2691GEN_LDUX(name, ldop, 0x17, op | 0x01, type); \
2692GEN_LDX(name, ldop, 0x17, op | 0x00, type)
79aceca5
FB
2693
2694/* lbz lbzu lbzux lbzx */
0c8aacd4 2695GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
79aceca5 2696/* lha lhau lhaux lhax */
0c8aacd4 2697GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
79aceca5 2698/* lhz lhzu lhzux lhzx */
0c8aacd4 2699GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
79aceca5 2700/* lwz lwzu lwzux lwzx */
0c8aacd4 2701GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
d9bce9d9 2702#if defined(TARGET_PPC64)
d9bce9d9 2703/* lwaux */
0c8aacd4 2704GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
d9bce9d9 2705/* lwax */
0c8aacd4 2706GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
d9bce9d9 2707/* ldux */
0c8aacd4 2708GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
d9bce9d9 2709/* ldx */
0c8aacd4 2710GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
99e300ef
BS
2711
2712static void gen_ld(DisasContext *ctx)
d9bce9d9 2713{
b61f2753 2714 TCGv EA;
d9bce9d9
JM
2715 if (Rc(ctx->opcode)) {
2716 if (unlikely(rA(ctx->opcode) == 0 ||
2717 rA(ctx->opcode) == rD(ctx->opcode))) {
e06fcd75 2718 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
d9bce9d9
JM
2719 return;
2720 }
2721 }
76db3ba4 2722 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 2723 EA = tcg_temp_new();
76db3ba4 2724 gen_addr_imm_index(ctx, EA, 0x03);
d9bce9d9
JM
2725 if (ctx->opcode & 0x02) {
2726 /* lwa (lwau is undefined) */
76db3ba4 2727 gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
d9bce9d9
JM
2728 } else {
2729 /* ld - ldu */
76db3ba4 2730 gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
d9bce9d9 2731 }
d9bce9d9 2732 if (Rc(ctx->opcode))
b61f2753
AJ
2733 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2734 tcg_temp_free(EA);
d9bce9d9 2735}
99e300ef 2736
54623277 2737/* lq */
99e300ef 2738static void gen_lq(DisasContext *ctx)
be147d08
JM
2739{
2740#if defined(CONFIG_USER_ONLY)
e06fcd75 2741 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
2742#else
2743 int ra, rd;
b61f2753 2744 TCGv EA;
be147d08
JM
2745
2746 /* Restore CPU state */
76db3ba4 2747 if (unlikely(ctx->mem_idx == 0)) {
e06fcd75 2748 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
2749 return;
2750 }
2751 ra = rA(ctx->opcode);
2752 rd = rD(ctx->opcode);
2753 if (unlikely((rd & 1) || rd == ra)) {
e06fcd75 2754 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
be147d08
JM
2755 return;
2756 }
76db3ba4 2757 if (unlikely(ctx->le_mode)) {
be147d08 2758 /* Little-endian mode is not handled */
e06fcd75 2759 gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
be147d08
JM
2760 return;
2761 }
76db3ba4 2762 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 2763 EA = tcg_temp_new();
76db3ba4
AJ
2764 gen_addr_imm_index(ctx, EA, 0x0F);
2765 gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2766 gen_addr_add(ctx, EA, EA, 8);
2767 gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
b61f2753 2768 tcg_temp_free(EA);
be147d08
JM
2769#endif
2770}
d9bce9d9 2771#endif
79aceca5
FB
2772
2773/*** Integer store ***/
0c8aacd4 2774#define GEN_ST(name, stop, opc, type) \
99e300ef 2775static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 2776{ \
76db3ba4
AJ
2777 TCGv EA; \
2778 gen_set_access_type(ctx, ACCESS_INT); \
2779 EA = tcg_temp_new(); \
2780 gen_addr_imm_index(ctx, EA, 0); \
2781 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753 2782 tcg_temp_free(EA); \
79aceca5
FB
2783}
2784
0c8aacd4 2785#define GEN_STU(name, stop, opc, type) \
99e300ef 2786static void glue(gen_, stop##u)(DisasContext *ctx) \
79aceca5 2787{ \
b61f2753 2788 TCGv EA; \
76a66253 2789 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 2790 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2791 return; \
9a64fbe4 2792 } \
76db3ba4 2793 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2794 EA = tcg_temp_new(); \
9d53c753 2795 if (type == PPC_64B) \
76db3ba4 2796 gen_addr_imm_index(ctx, EA, 0x03); \
9d53c753 2797 else \
76db3ba4
AJ
2798 gen_addr_imm_index(ctx, EA, 0); \
2799 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753
AJ
2800 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2801 tcg_temp_free(EA); \
79aceca5
FB
2802}
2803
0c8aacd4 2804#define GEN_STUX(name, stop, opc2, opc3, type) \
99e300ef 2805static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 2806{ \
b61f2753 2807 TCGv EA; \
76a66253 2808 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 2809 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2810 return; \
9a64fbe4 2811 } \
76db3ba4 2812 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2813 EA = tcg_temp_new(); \
76db3ba4
AJ
2814 gen_addr_reg_index(ctx, EA); \
2815 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753
AJ
2816 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2817 tcg_temp_free(EA); \
79aceca5
FB
2818}
2819
cd6e9320
TH
2820#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
2821static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 2822{ \
76db3ba4
AJ
2823 TCGv EA; \
2824 gen_set_access_type(ctx, ACCESS_INT); \
2825 EA = tcg_temp_new(); \
2826 gen_addr_reg_index(ctx, EA); \
2827 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753 2828 tcg_temp_free(EA); \
79aceca5 2829}
cd6e9320
TH
2830#define GEN_STX(name, stop, opc2, opc3, type) \
2831 GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
79aceca5 2832
0c8aacd4
AJ
2833#define GEN_STS(name, stop, op, type) \
2834GEN_ST(name, stop, op | 0x20, type); \
2835GEN_STU(name, stop, op | 0x21, type); \
2836GEN_STUX(name, stop, 0x17, op | 0x01, type); \
2837GEN_STX(name, stop, 0x17, op | 0x00, type)
79aceca5
FB
2838
2839/* stb stbu stbux stbx */
0c8aacd4 2840GEN_STS(stb, st8, 0x06, PPC_INTEGER);
79aceca5 2841/* sth sthu sthux sthx */
0c8aacd4 2842GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
79aceca5 2843/* stw stwu stwux stwx */
0c8aacd4 2844GEN_STS(stw, st32, 0x04, PPC_INTEGER);
d9bce9d9 2845#if defined(TARGET_PPC64)
0c8aacd4
AJ
2846GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
2847GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
99e300ef
BS
2848
2849static void gen_std(DisasContext *ctx)
d9bce9d9 2850{
be147d08 2851 int rs;
b61f2753 2852 TCGv EA;
be147d08
JM
2853
2854 rs = rS(ctx->opcode);
2855 if ((ctx->opcode & 0x3) == 0x2) {
2856#if defined(CONFIG_USER_ONLY)
e06fcd75 2857 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
2858#else
2859 /* stq */
76db3ba4 2860 if (unlikely(ctx->mem_idx == 0)) {
e06fcd75 2861 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
2862 return;
2863 }
2864 if (unlikely(rs & 1)) {
e06fcd75 2865 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
d9bce9d9
JM
2866 return;
2867 }
76db3ba4 2868 if (unlikely(ctx->le_mode)) {
be147d08 2869 /* Little-endian mode is not handled */
e06fcd75 2870 gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
be147d08
JM
2871 return;
2872 }
76db3ba4 2873 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 2874 EA = tcg_temp_new();
76db3ba4
AJ
2875 gen_addr_imm_index(ctx, EA, 0x03);
2876 gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2877 gen_addr_add(ctx, EA, EA, 8);
2878 gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
b61f2753 2879 tcg_temp_free(EA);
be147d08
JM
2880#endif
2881 } else {
2882 /* std / stdu */
2883 if (Rc(ctx->opcode)) {
2884 if (unlikely(rA(ctx->opcode) == 0)) {
e06fcd75 2885 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
be147d08
JM
2886 return;
2887 }
2888 }
76db3ba4 2889 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 2890 EA = tcg_temp_new();
76db3ba4
AJ
2891 gen_addr_imm_index(ctx, EA, 0x03);
2892 gen_qemu_st64(ctx, cpu_gpr[rs], EA);
be147d08 2893 if (Rc(ctx->opcode))
b61f2753
AJ
2894 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2895 tcg_temp_free(EA);
d9bce9d9 2896 }
d9bce9d9
JM
2897}
2898#endif
79aceca5
FB
2899/*** Integer load and store with byte reverse ***/
2900/* lhbrx */
86178a57 2901static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2902{
76db3ba4
AJ
2903 tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2904 if (likely(!ctx->le_mode)) {
fa3966a3 2905 tcg_gen_bswap16_tl(arg1, arg1);
76db3ba4 2906 }
b61f2753 2907}
0c8aacd4 2908GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
b61f2753 2909
79aceca5 2910/* lwbrx */
86178a57 2911static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2912{
76db3ba4
AJ
2913 tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2914 if (likely(!ctx->le_mode)) {
fa3966a3 2915 tcg_gen_bswap32_tl(arg1, arg1);
76db3ba4 2916 }
b61f2753 2917}
0c8aacd4 2918GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
b61f2753 2919
cd6e9320
TH
2920#if defined(TARGET_PPC64)
2921/* ldbrx */
2922static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
2923{
2924 tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
2925 if (likely(!ctx->le_mode)) {
2926 tcg_gen_bswap64_tl(arg1, arg1);
2927 }
2928}
2929GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
2930#endif /* TARGET_PPC64 */
2931
79aceca5 2932/* sthbrx */
86178a57 2933static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2934{
76db3ba4 2935 if (likely(!ctx->le_mode)) {
76db3ba4
AJ
2936 TCGv t0 = tcg_temp_new();
2937 tcg_gen_ext16u_tl(t0, arg1);
fa3966a3 2938 tcg_gen_bswap16_tl(t0, t0);
76db3ba4
AJ
2939 tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2940 tcg_temp_free(t0);
76db3ba4
AJ
2941 } else {
2942 tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2943 }
b61f2753 2944}
0c8aacd4 2945GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
b61f2753 2946
79aceca5 2947/* stwbrx */
86178a57 2948static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2949{
76db3ba4 2950 if (likely(!ctx->le_mode)) {
fa3966a3
AJ
2951 TCGv t0 = tcg_temp_new();
2952 tcg_gen_ext32u_tl(t0, arg1);
2953 tcg_gen_bswap32_tl(t0, t0);
76db3ba4
AJ
2954 tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2955 tcg_temp_free(t0);
76db3ba4
AJ
2956 } else {
2957 tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2958 }
b61f2753 2959}
0c8aacd4 2960GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
79aceca5 2961
cd6e9320
TH
2962#if defined(TARGET_PPC64)
2963/* stdbrx */
2964static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
2965{
2966 if (likely(!ctx->le_mode)) {
2967 TCGv t0 = tcg_temp_new();
2968 tcg_gen_bswap64_tl(t0, arg1);
2969 tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
2970 tcg_temp_free(t0);
2971 } else {
2972 tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
2973 }
2974}
2975GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
2976#endif /* TARGET_PPC64 */
2977
79aceca5 2978/*** Integer load and store multiple ***/
99e300ef 2979
54623277 2980/* lmw */
99e300ef 2981static void gen_lmw(DisasContext *ctx)
79aceca5 2982{
76db3ba4
AJ
2983 TCGv t0;
2984 TCGv_i32 t1;
2985 gen_set_access_type(ctx, ACCESS_INT);
76a66253 2986 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 2987 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
2988 t0 = tcg_temp_new();
2989 t1 = tcg_const_i32(rD(ctx->opcode));
2990 gen_addr_imm_index(ctx, t0, 0);
2f5a189c 2991 gen_helper_lmw(cpu_env, t0, t1);
ff4a62cd
AJ
2992 tcg_temp_free(t0);
2993 tcg_temp_free_i32(t1);
79aceca5
FB
2994}
2995
2996/* stmw */
99e300ef 2997static void gen_stmw(DisasContext *ctx)
79aceca5 2998{
76db3ba4
AJ
2999 TCGv t0;
3000 TCGv_i32 t1;
3001 gen_set_access_type(ctx, ACCESS_INT);
76a66253 3002 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3003 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3004 t0 = tcg_temp_new();
3005 t1 = tcg_const_i32(rS(ctx->opcode));
3006 gen_addr_imm_index(ctx, t0, 0);
2f5a189c 3007 gen_helper_stmw(cpu_env, t0, t1);
ff4a62cd
AJ
3008 tcg_temp_free(t0);
3009 tcg_temp_free_i32(t1);
79aceca5
FB
3010}
3011
3012/*** Integer load and store strings ***/
54623277 3013
79aceca5 3014/* lswi */
3fc6c082 3015/* PowerPC32 specification says we must generate an exception if
9a64fbe4
FB
3016 * rA is in the range of registers to be loaded.
3017 * In an other hand, IBM says this is valid, but rA won't be loaded.
3018 * For now, I'll follow the spec...
3019 */
99e300ef 3020static void gen_lswi(DisasContext *ctx)
79aceca5 3021{
dfbc799d
AJ
3022 TCGv t0;
3023 TCGv_i32 t1, t2;
79aceca5
FB
3024 int nb = NB(ctx->opcode);
3025 int start = rD(ctx->opcode);
9a64fbe4 3026 int ra = rA(ctx->opcode);
79aceca5
FB
3027 int nr;
3028
3029 if (nb == 0)
3030 nb = 32;
3031 nr = nb / 4;
76a66253
JM
3032 if (unlikely(((start + nr) > 32 &&
3033 start <= ra && (start + nr - 32) > ra) ||
3034 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
e06fcd75 3035 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
9fddaa0c 3036 return;
297d8e62 3037 }
76db3ba4 3038 gen_set_access_type(ctx, ACCESS_INT);
8dd4983c 3039 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3040 gen_update_nip(ctx, ctx->nip - 4);
dfbc799d 3041 t0 = tcg_temp_new();
76db3ba4 3042 gen_addr_register(ctx, t0);
dfbc799d
AJ
3043 t1 = tcg_const_i32(nb);
3044 t2 = tcg_const_i32(start);
2f5a189c 3045 gen_helper_lsw(cpu_env, t0, t1, t2);
dfbc799d
AJ
3046 tcg_temp_free(t0);
3047 tcg_temp_free_i32(t1);
3048 tcg_temp_free_i32(t2);
79aceca5
FB
3049}
3050
3051/* lswx */
99e300ef 3052static void gen_lswx(DisasContext *ctx)
79aceca5 3053{
76db3ba4
AJ
3054 TCGv t0;
3055 TCGv_i32 t1, t2, t3;
3056 gen_set_access_type(ctx, ACCESS_INT);
76a66253 3057 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3058 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3059 t0 = tcg_temp_new();
3060 gen_addr_reg_index(ctx, t0);
3061 t1 = tcg_const_i32(rD(ctx->opcode));
3062 t2 = tcg_const_i32(rA(ctx->opcode));
3063 t3 = tcg_const_i32(rB(ctx->opcode));
2f5a189c 3064 gen_helper_lswx(cpu_env, t0, t1, t2, t3);
dfbc799d
AJ
3065 tcg_temp_free(t0);
3066 tcg_temp_free_i32(t1);
3067 tcg_temp_free_i32(t2);
3068 tcg_temp_free_i32(t3);
79aceca5
FB
3069}
3070
3071/* stswi */
99e300ef 3072static void gen_stswi(DisasContext *ctx)
79aceca5 3073{
76db3ba4
AJ
3074 TCGv t0;
3075 TCGv_i32 t1, t2;
4b3686fa 3076 int nb = NB(ctx->opcode);
76db3ba4 3077 gen_set_access_type(ctx, ACCESS_INT);
76a66253 3078 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3079 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3080 t0 = tcg_temp_new();
3081 gen_addr_register(ctx, t0);
4b3686fa
FB
3082 if (nb == 0)
3083 nb = 32;
dfbc799d 3084 t1 = tcg_const_i32(nb);
76db3ba4 3085 t2 = tcg_const_i32(rS(ctx->opcode));
2f5a189c 3086 gen_helper_stsw(cpu_env, t0, t1, t2);
dfbc799d
AJ
3087 tcg_temp_free(t0);
3088 tcg_temp_free_i32(t1);
3089 tcg_temp_free_i32(t2);
79aceca5
FB
3090}
3091
3092/* stswx */
99e300ef 3093static void gen_stswx(DisasContext *ctx)
79aceca5 3094{
76db3ba4
AJ
3095 TCGv t0;
3096 TCGv_i32 t1, t2;
3097 gen_set_access_type(ctx, ACCESS_INT);
8dd4983c 3098 /* NIP cannot be restored if the memory exception comes from an helper */
5fafdf24 3099 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3100 t0 = tcg_temp_new();
3101 gen_addr_reg_index(ctx, t0);
3102 t1 = tcg_temp_new_i32();
dfbc799d
AJ
3103 tcg_gen_trunc_tl_i32(t1, cpu_xer);
3104 tcg_gen_andi_i32(t1, t1, 0x7F);
76db3ba4 3105 t2 = tcg_const_i32(rS(ctx->opcode));
2f5a189c 3106 gen_helper_stsw(cpu_env, t0, t1, t2);
dfbc799d
AJ
3107 tcg_temp_free(t0);
3108 tcg_temp_free_i32(t1);
3109 tcg_temp_free_i32(t2);
79aceca5
FB
3110}
3111
3112/*** Memory synchronisation ***/
3113/* eieio */
99e300ef 3114static void gen_eieio(DisasContext *ctx)
79aceca5 3115{
79aceca5
FB
3116}
3117
3118/* isync */
99e300ef 3119static void gen_isync(DisasContext *ctx)
79aceca5 3120{
e06fcd75 3121 gen_stop_exception(ctx);
79aceca5
FB
3122}
3123
111bfab3 3124/* lwarx */
99e300ef 3125static void gen_lwarx(DisasContext *ctx)
79aceca5 3126{
76db3ba4 3127 TCGv t0;
18b21a2f 3128 TCGv gpr = cpu_gpr[rD(ctx->opcode)];
76db3ba4
AJ
3129 gen_set_access_type(ctx, ACCESS_RES);
3130 t0 = tcg_temp_local_new();
3131 gen_addr_reg_index(ctx, t0);
cf360a32 3132 gen_check_align(ctx, t0, 0x03);
18b21a2f 3133 gen_qemu_ld32u(ctx, gpr, t0);
cf360a32 3134 tcg_gen_mov_tl(cpu_reserve, t0);
1328c2bf 3135 tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
cf360a32 3136 tcg_temp_free(t0);
79aceca5
FB
3137}
3138
4425265b
NF
3139#if defined(CONFIG_USER_ONLY)
3140static void gen_conditional_store (DisasContext *ctx, TCGv EA,
3141 int reg, int size)
3142{
3143 TCGv t0 = tcg_temp_new();
3144 uint32_t save_exception = ctx->exception;
3145
1328c2bf 3146 tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea));
4425265b 3147 tcg_gen_movi_tl(t0, (size << 5) | reg);
1328c2bf 3148 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
4425265b
NF
3149 tcg_temp_free(t0);
3150 gen_update_nip(ctx, ctx->nip-4);
3151 ctx->exception = POWERPC_EXCP_BRANCH;
3152 gen_exception(ctx, POWERPC_EXCP_STCX);
3153 ctx->exception = save_exception;
3154}
3155#endif
3156
79aceca5 3157/* stwcx. */
e8eaa2c0 3158static void gen_stwcx_(DisasContext *ctx)
79aceca5 3159{
76db3ba4
AJ
3160 TCGv t0;
3161 gen_set_access_type(ctx, ACCESS_RES);
3162 t0 = tcg_temp_local_new();
3163 gen_addr_reg_index(ctx, t0);
cf360a32 3164 gen_check_align(ctx, t0, 0x03);
4425265b
NF
3165#if defined(CONFIG_USER_ONLY)
3166 gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
3167#else
3168 {
3169 int l1;
3170
da91a00f 3171 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
4425265b
NF
3172 l1 = gen_new_label();
3173 tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3174 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3175 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3176 gen_set_label(l1);
3177 tcg_gen_movi_tl(cpu_reserve, -1);
3178 }
3179#endif
cf360a32 3180 tcg_temp_free(t0);
79aceca5
FB
3181}
3182
426613db 3183#if defined(TARGET_PPC64)
426613db 3184/* ldarx */
99e300ef 3185static void gen_ldarx(DisasContext *ctx)
426613db 3186{
76db3ba4 3187 TCGv t0;
18b21a2f 3188 TCGv gpr = cpu_gpr[rD(ctx->opcode)];
76db3ba4
AJ
3189 gen_set_access_type(ctx, ACCESS_RES);
3190 t0 = tcg_temp_local_new();
3191 gen_addr_reg_index(ctx, t0);
cf360a32 3192 gen_check_align(ctx, t0, 0x07);
18b21a2f 3193 gen_qemu_ld64(ctx, gpr, t0);
cf360a32 3194 tcg_gen_mov_tl(cpu_reserve, t0);
1328c2bf 3195 tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
cf360a32 3196 tcg_temp_free(t0);
426613db
JM
3197}
3198
3199/* stdcx. */
e8eaa2c0 3200static void gen_stdcx_(DisasContext *ctx)
426613db 3201{
76db3ba4
AJ
3202 TCGv t0;
3203 gen_set_access_type(ctx, ACCESS_RES);
3204 t0 = tcg_temp_local_new();
3205 gen_addr_reg_index(ctx, t0);
cf360a32 3206 gen_check_align(ctx, t0, 0x07);
4425265b
NF
3207#if defined(CONFIG_USER_ONLY)
3208 gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
3209#else
3210 {
3211 int l1;
da91a00f 3212 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
4425265b
NF
3213 l1 = gen_new_label();
3214 tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3215 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3216 gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3217 gen_set_label(l1);
3218 tcg_gen_movi_tl(cpu_reserve, -1);
3219 }
3220#endif
cf360a32 3221 tcg_temp_free(t0);
426613db
JM
3222}
3223#endif /* defined(TARGET_PPC64) */
3224
79aceca5 3225/* sync */
99e300ef 3226static void gen_sync(DisasContext *ctx)
79aceca5 3227{
79aceca5
FB
3228}
3229
0db1b20e 3230/* wait */
99e300ef 3231static void gen_wait(DisasContext *ctx)
0db1b20e 3232{
931ff272 3233 TCGv_i32 t0 = tcg_temp_new_i32();
259186a7
AF
3234 tcg_gen_st_i32(t0, cpu_env,
3235 -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
931ff272 3236 tcg_temp_free_i32(t0);
0db1b20e 3237 /* Stop translation, as the CPU is supposed to sleep from now */
e06fcd75 3238 gen_exception_err(ctx, EXCP_HLT, 1);
0db1b20e
JM
3239}
3240
79aceca5 3241/*** Floating-point load ***/
a0d7d5a7 3242#define GEN_LDF(name, ldop, opc, type) \
99e300ef 3243static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 3244{ \
a0d7d5a7 3245 TCGv EA; \
76a66253 3246 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3247 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3248 return; \
3249 } \
76db3ba4 3250 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3251 EA = tcg_temp_new(); \
76db3ba4
AJ
3252 gen_addr_imm_index(ctx, EA, 0); \
3253 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7 3254 tcg_temp_free(EA); \
79aceca5
FB
3255}
3256
a0d7d5a7 3257#define GEN_LDUF(name, ldop, opc, type) \
99e300ef 3258static void glue(gen_, name##u)(DisasContext *ctx) \
79aceca5 3259{ \
a0d7d5a7 3260 TCGv EA; \
76a66253 3261 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3262 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3263 return; \
3264 } \
76a66253 3265 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3266 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3267 return; \
9a64fbe4 3268 } \
76db3ba4 3269 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3270 EA = tcg_temp_new(); \
76db3ba4
AJ
3271 gen_addr_imm_index(ctx, EA, 0); \
3272 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7
AJ
3273 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3274 tcg_temp_free(EA); \
79aceca5
FB
3275}
3276
a0d7d5a7 3277#define GEN_LDUXF(name, ldop, opc, type) \
99e300ef 3278static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 3279{ \
a0d7d5a7 3280 TCGv EA; \
76a66253 3281 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3282 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3283 return; \
3284 } \
76a66253 3285 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3286 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3287 return; \
9a64fbe4 3288 } \
76db3ba4 3289 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3290 EA = tcg_temp_new(); \
76db3ba4
AJ
3291 gen_addr_reg_index(ctx, EA); \
3292 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7
AJ
3293 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3294 tcg_temp_free(EA); \
79aceca5
FB
3295}
3296
a0d7d5a7 3297#define GEN_LDXF(name, ldop, opc2, opc3, type) \
99e300ef 3298static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 3299{ \
a0d7d5a7 3300 TCGv EA; \
76a66253 3301 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3302 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3303 return; \
3304 } \
76db3ba4 3305 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3306 EA = tcg_temp_new(); \
76db3ba4
AJ
3307 gen_addr_reg_index(ctx, EA); \
3308 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7 3309 tcg_temp_free(EA); \
79aceca5
FB
3310}
3311
a0d7d5a7
AJ
3312#define GEN_LDFS(name, ldop, op, type) \
3313GEN_LDF(name, ldop, op | 0x20, type); \
3314GEN_LDUF(name, ldop, op | 0x21, type); \
3315GEN_LDUXF(name, ldop, op | 0x01, type); \
3316GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3317
636aa200 3318static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
a0d7d5a7
AJ
3319{
3320 TCGv t0 = tcg_temp_new();
3321 TCGv_i32 t1 = tcg_temp_new_i32();
76db3ba4 3322 gen_qemu_ld32u(ctx, t0, arg2);
a0d7d5a7
AJ
3323 tcg_gen_trunc_tl_i32(t1, t0);
3324 tcg_temp_free(t0);
8e703949 3325 gen_helper_float32_to_float64(arg1, cpu_env, t1);
a0d7d5a7
AJ
3326 tcg_temp_free_i32(t1);
3327}
79aceca5 3328
a0d7d5a7
AJ
3329 /* lfd lfdu lfdux lfdx */
3330GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3331 /* lfs lfsu lfsux lfsx */
3332GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
79aceca5 3333
05050ee8
AJ
3334/* lfdp */
3335static void gen_lfdp(DisasContext *ctx)
3336{
3337 TCGv EA;
3338 if (unlikely(!ctx->fpu_enabled)) {
3339 gen_exception(ctx, POWERPC_EXCP_FPU);
3340 return;
3341 }
3342 gen_set_access_type(ctx, ACCESS_FLOAT);
3343 EA = tcg_temp_new();
3344 gen_addr_imm_index(ctx, EA, 0); \
3345 if (unlikely(ctx->le_mode)) {
3346 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3347 tcg_gen_addi_tl(EA, EA, 8);
3348 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3349 } else {
3350 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3351 tcg_gen_addi_tl(EA, EA, 8);
3352 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3353 }
3354 tcg_temp_free(EA);
3355}
3356
3357/* lfdpx */
3358static void gen_lfdpx(DisasContext *ctx)
3359{
3360 TCGv EA;
3361 if (unlikely(!ctx->fpu_enabled)) {
3362 gen_exception(ctx, POWERPC_EXCP_FPU);
3363 return;
3364 }
3365 gen_set_access_type(ctx, ACCESS_FLOAT);
3366 EA = tcg_temp_new();
3367 gen_addr_reg_index(ctx, EA);
3368 if (unlikely(ctx->le_mode)) {
3369 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3370 tcg_gen_addi_tl(EA, EA, 8);
3371 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3372 } else {
3373 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3374 tcg_gen_addi_tl(EA, EA, 8);
3375 gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3376 }
3377 tcg_temp_free(EA);
3378}
3379
199f830d
AJ
3380/* lfiwax */
3381static void gen_lfiwax(DisasContext *ctx)
3382{
3383 TCGv EA;
3384 TCGv t0;
3385 if (unlikely(!ctx->fpu_enabled)) {
3386 gen_exception(ctx, POWERPC_EXCP_FPU);
3387 return;
3388 }
3389 gen_set_access_type(ctx, ACCESS_FLOAT);
3390 EA = tcg_temp_new();
3391 t0 = tcg_temp_new();
3392 gen_addr_reg_index(ctx, EA);
909eedb7 3393 gen_qemu_ld32s(ctx, t0, EA);
199f830d 3394 tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
199f830d
AJ
3395 tcg_temp_free(EA);
3396 tcg_temp_free(t0);
3397}
3398
79aceca5 3399/*** Floating-point store ***/
a0d7d5a7 3400#define GEN_STF(name, stop, opc, type) \
99e300ef 3401static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 3402{ \
a0d7d5a7 3403 TCGv EA; \
76a66253 3404 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3405 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3406 return; \
3407 } \
76db3ba4 3408 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3409 EA = tcg_temp_new(); \
76db3ba4
AJ
3410 gen_addr_imm_index(ctx, EA, 0); \
3411 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7 3412 tcg_temp_free(EA); \
79aceca5
FB
3413}
3414
a0d7d5a7 3415#define GEN_STUF(name, stop, opc, type) \
99e300ef 3416static void glue(gen_, name##u)(DisasContext *ctx) \
79aceca5 3417{ \
a0d7d5a7 3418 TCGv EA; \
76a66253 3419 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3420 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3421 return; \
3422 } \
76a66253 3423 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3424 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3425 return; \
9a64fbe4 3426 } \
76db3ba4 3427 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3428 EA = tcg_temp_new(); \
76db3ba4
AJ
3429 gen_addr_imm_index(ctx, EA, 0); \
3430 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7
AJ
3431 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3432 tcg_temp_free(EA); \
79aceca5
FB
3433}
3434
a0d7d5a7 3435#define GEN_STUXF(name, stop, opc, type) \
99e300ef 3436static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 3437{ \
a0d7d5a7 3438 TCGv EA; \
76a66253 3439 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3440 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3441 return; \
3442 } \
76a66253 3443 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3444 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3445 return; \
9a64fbe4 3446 } \
76db3ba4 3447 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3448 EA = tcg_temp_new(); \
76db3ba4
AJ
3449 gen_addr_reg_index(ctx, EA); \
3450 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7
AJ
3451 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3452 tcg_temp_free(EA); \
79aceca5
FB
3453}
3454
a0d7d5a7 3455#define GEN_STXF(name, stop, opc2, opc3, type) \
99e300ef 3456static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 3457{ \
a0d7d5a7 3458 TCGv EA; \
76a66253 3459 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3460 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3461 return; \
3462 } \
76db3ba4 3463 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3464 EA = tcg_temp_new(); \
76db3ba4
AJ
3465 gen_addr_reg_index(ctx, EA); \
3466 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7 3467 tcg_temp_free(EA); \
79aceca5
FB
3468}
3469
a0d7d5a7
AJ
3470#define GEN_STFS(name, stop, op, type) \
3471GEN_STF(name, stop, op | 0x20, type); \
3472GEN_STUF(name, stop, op | 0x21, type); \
3473GEN_STUXF(name, stop, op | 0x01, type); \
3474GEN_STXF(name, stop, 0x17, op | 0x00, type)
3475
636aa200 3476static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
a0d7d5a7
AJ
3477{
3478 TCGv_i32 t0 = tcg_temp_new_i32();
3479 TCGv t1 = tcg_temp_new();
8e703949 3480 gen_helper_float64_to_float32(t0, cpu_env, arg1);
a0d7d5a7
AJ
3481 tcg_gen_extu_i32_tl(t1, t0);
3482 tcg_temp_free_i32(t0);
76db3ba4 3483 gen_qemu_st32(ctx, t1, arg2);
a0d7d5a7
AJ
3484 tcg_temp_free(t1);
3485}
79aceca5
FB
3486
3487/* stfd stfdu stfdux stfdx */
a0d7d5a7 3488GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
79aceca5 3489/* stfs stfsu stfsux stfsx */
a0d7d5a7 3490GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
79aceca5 3491
44bc0c4d
AJ
3492/* stfdp */
3493static void gen_stfdp(DisasContext *ctx)
3494{
3495 TCGv EA;
3496 if (unlikely(!ctx->fpu_enabled)) {
3497 gen_exception(ctx, POWERPC_EXCP_FPU);
3498 return;
3499 }
3500 gen_set_access_type(ctx, ACCESS_FLOAT);
3501 EA = tcg_temp_new();
3502 gen_addr_imm_index(ctx, EA, 0); \
3503 if (unlikely(ctx->le_mode)) {
3504 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3505 tcg_gen_addi_tl(EA, EA, 8);
3506 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3507 } else {
3508 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3509 tcg_gen_addi_tl(EA, EA, 8);
3510 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3511 }
3512 tcg_temp_free(EA);
3513}
3514
3515/* stfdpx */
3516static void gen_stfdpx(DisasContext *ctx)
3517{
3518 TCGv EA;
3519 if (unlikely(!ctx->fpu_enabled)) {
3520 gen_exception(ctx, POWERPC_EXCP_FPU);
3521 return;
3522 }
3523 gen_set_access_type(ctx, ACCESS_FLOAT);
3524 EA = tcg_temp_new();
3525 gen_addr_reg_index(ctx, EA);
3526 if (unlikely(ctx->le_mode)) {
3527 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3528 tcg_gen_addi_tl(EA, EA, 8);
3529 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3530 } else {
3531 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
3532 tcg_gen_addi_tl(EA, EA, 8);
3533 gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
3534 }
3535 tcg_temp_free(EA);
3536}
3537
79aceca5 3538/* Optional: */
636aa200 3539static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
a0d7d5a7
AJ
3540{
3541 TCGv t0 = tcg_temp_new();
3542 tcg_gen_trunc_i64_tl(t0, arg1),
76db3ba4 3543 gen_qemu_st32(ctx, t0, arg2);
a0d7d5a7
AJ
3544 tcg_temp_free(t0);
3545}
79aceca5 3546/* stfiwx */
a0d7d5a7 3547GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
79aceca5 3548
697ab892
DG
3549static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
3550{
3551#if defined(TARGET_PPC64)
3552 if (ctx->has_cfar)
3553 tcg_gen_movi_tl(cpu_cfar, nip);
3554#endif
3555}
3556
79aceca5 3557/*** Branch ***/
636aa200 3558static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c1942362
FB
3559{
3560 TranslationBlock *tb;
3561 tb = ctx->tb;
e0c8f9ce 3562 if (NARROW_MODE(ctx)) {
a2ffb812 3563 dest = (uint32_t) dest;
e0c8f9ce 3564 }
57fec1fe 3565 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
8cbcb4fa 3566 likely(!ctx->singlestep_enabled)) {
57fec1fe 3567 tcg_gen_goto_tb(n);
a2ffb812 3568 tcg_gen_movi_tl(cpu_nip, dest & ~3);
8cfd0495 3569 tcg_gen_exit_tb((uintptr_t)tb + n);
c1942362 3570 } else {
a2ffb812 3571 tcg_gen_movi_tl(cpu_nip, dest & ~3);
8cbcb4fa
AJ
3572 if (unlikely(ctx->singlestep_enabled)) {
3573 if ((ctx->singlestep_enabled &
bdc4e053 3574 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
f0cc4aa8
JG
3575 (ctx->exception == POWERPC_EXCP_BRANCH ||
3576 ctx->exception == POWERPC_EXCP_TRACE)) {
8cbcb4fa
AJ
3577 target_ulong tmp = ctx->nip;
3578 ctx->nip = dest;
e06fcd75 3579 gen_exception(ctx, POWERPC_EXCP_TRACE);
8cbcb4fa
AJ
3580 ctx->nip = tmp;
3581 }
3582 if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
e06fcd75 3583 gen_debug_exception(ctx);
8cbcb4fa
AJ
3584 }
3585 }
57fec1fe 3586 tcg_gen_exit_tb(0);
c1942362 3587 }
c53be334
FB
3588}
3589
636aa200 3590static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
e1833e1f 3591{
e0c8f9ce
RH
3592 if (NARROW_MODE(ctx)) {
3593 nip = (uint32_t)nip;
3594 }
3595 tcg_gen_movi_tl(cpu_lr, nip);
e1833e1f
JM
3596}
3597
79aceca5 3598/* b ba bl bla */
99e300ef 3599static void gen_b(DisasContext *ctx)
79aceca5 3600{
76a66253 3601 target_ulong li, target;
38a64f9d 3602
8cbcb4fa 3603 ctx->exception = POWERPC_EXCP_BRANCH;
38a64f9d 3604 /* sign extend LI */
e0c8f9ce
RH
3605 li = LI(ctx->opcode);
3606 li = (li ^ 0x02000000) - 0x02000000;
3607 if (likely(AA(ctx->opcode) == 0)) {
046d6672 3608 target = ctx->nip + li - 4;
e0c8f9ce 3609 } else {
9a64fbe4 3610 target = li;
e0c8f9ce
RH
3611 }
3612 if (LK(ctx->opcode)) {
e1833e1f 3613 gen_setlr(ctx, ctx->nip);
e0c8f9ce 3614 }
697ab892 3615 gen_update_cfar(ctx, ctx->nip);
c1942362 3616 gen_goto_tb(ctx, 0, target);
79aceca5
FB
3617}
3618
e98a6e40
FB
3619#define BCOND_IM 0
3620#define BCOND_LR 1
3621#define BCOND_CTR 2
3622
636aa200 3623static inline void gen_bcond(DisasContext *ctx, int type)
d9bce9d9 3624{
d9bce9d9 3625 uint32_t bo = BO(ctx->opcode);
05f92404 3626 int l1;
a2ffb812 3627 TCGv target;
e98a6e40 3628
8cbcb4fa 3629 ctx->exception = POWERPC_EXCP_BRANCH;
a2ffb812 3630 if (type == BCOND_LR || type == BCOND_CTR) {
a7812ae4 3631 target = tcg_temp_local_new();
a2ffb812
AJ
3632 if (type == BCOND_CTR)
3633 tcg_gen_mov_tl(target, cpu_ctr);
3634 else
3635 tcg_gen_mov_tl(target, cpu_lr);
d2e9fd8f 3636 } else {
3637 TCGV_UNUSED(target);
e98a6e40 3638 }
e1833e1f
JM
3639 if (LK(ctx->opcode))
3640 gen_setlr(ctx, ctx->nip);
a2ffb812
AJ
3641 l1 = gen_new_label();
3642 if ((bo & 0x4) == 0) {
3643 /* Decrement and test CTR */
a7812ae4 3644 TCGv temp = tcg_temp_new();
a2ffb812 3645 if (unlikely(type == BCOND_CTR)) {
e06fcd75 3646 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
a2ffb812
AJ
3647 return;
3648 }
3649 tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
e0c8f9ce 3650 if (NARROW_MODE(ctx)) {
a2ffb812 3651 tcg_gen_ext32u_tl(temp, cpu_ctr);
e0c8f9ce 3652 } else {
a2ffb812 3653 tcg_gen_mov_tl(temp, cpu_ctr);
e0c8f9ce 3654 }
a2ffb812
AJ
3655 if (bo & 0x2) {
3656 tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3657 } else {
3658 tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
e98a6e40 3659 }
a7812ae4 3660 tcg_temp_free(temp);
a2ffb812
AJ
3661 }
3662 if ((bo & 0x10) == 0) {
3663 /* Test CR */
3664 uint32_t bi = BI(ctx->opcode);
3665 uint32_t mask = 1 << (3 - (bi & 0x03));
a7812ae4 3666 TCGv_i32 temp = tcg_temp_new_i32();
a2ffb812 3667
d9bce9d9 3668 if (bo & 0x8) {
a2ffb812
AJ
3669 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3670 tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
d9bce9d9 3671 } else {
a2ffb812
AJ
3672 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3673 tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
d9bce9d9 3674 }
a7812ae4 3675 tcg_temp_free_i32(temp);
d9bce9d9 3676 }
697ab892 3677 gen_update_cfar(ctx, ctx->nip);
e98a6e40 3678 if (type == BCOND_IM) {
a2ffb812
AJ
3679 target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3680 if (likely(AA(ctx->opcode) == 0)) {
3681 gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3682 } else {
3683 gen_goto_tb(ctx, 0, li);
3684 }
c53be334 3685 gen_set_label(l1);
c1942362 3686 gen_goto_tb(ctx, 1, ctx->nip);
e98a6e40 3687 } else {
e0c8f9ce 3688 if (NARROW_MODE(ctx)) {
a2ffb812 3689 tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
e0c8f9ce 3690 } else {
a2ffb812 3691 tcg_gen_andi_tl(cpu_nip, target, ~3);
e0c8f9ce 3692 }
a2ffb812
AJ
3693 tcg_gen_exit_tb(0);
3694 gen_set_label(l1);
e0c8f9ce 3695 gen_update_nip(ctx, ctx->nip);
57fec1fe 3696 tcg_gen_exit_tb(0);
08e46e54 3697 }
e98a6e40
FB
3698}
3699
99e300ef 3700static void gen_bc(DisasContext *ctx)
3b46e624 3701{
e98a6e40
FB
3702 gen_bcond(ctx, BCOND_IM);
3703}
3704
99e300ef 3705static void gen_bcctr(DisasContext *ctx)
3b46e624 3706{
e98a6e40
FB
3707 gen_bcond(ctx, BCOND_CTR);
3708}
3709
99e300ef 3710static void gen_bclr(DisasContext *ctx)
3b46e624 3711{
e98a6e40
FB
3712 gen_bcond(ctx, BCOND_LR);
3713}
79aceca5
FB
3714
3715/*** Condition register logical ***/
e1571908 3716#define GEN_CRLOGIC(name, tcg_op, opc) \
99e300ef 3717static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 3718{ \
fc0d441e
JM
3719 uint8_t bitmask; \
3720 int sh; \
a7812ae4 3721 TCGv_i32 t0, t1; \
fc0d441e 3722 sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
a7812ae4 3723 t0 = tcg_temp_new_i32(); \
fc0d441e 3724 if (sh > 0) \
fea0c503 3725 tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \
fc0d441e 3726 else if (sh < 0) \
fea0c503 3727 tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \
e1571908 3728 else \
fea0c503 3729 tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \
a7812ae4 3730 t1 = tcg_temp_new_i32(); \
fc0d441e
JM
3731 sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
3732 if (sh > 0) \
fea0c503 3733 tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \
fc0d441e 3734 else if (sh < 0) \
fea0c503 3735 tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \
e1571908 3736 else \
fea0c503
AJ
3737 tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \
3738 tcg_op(t0, t0, t1); \
fc0d441e 3739 bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
fea0c503
AJ
3740 tcg_gen_andi_i32(t0, t0, bitmask); \
3741 tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
3742 tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \
a7812ae4
PB
3743 tcg_temp_free_i32(t0); \
3744 tcg_temp_free_i32(t1); \
79aceca5
FB
3745}
3746
3747/* crand */
e1571908 3748GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
79aceca5 3749/* crandc */
e1571908 3750GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
79aceca5 3751/* creqv */
e1571908 3752GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
79aceca5 3753/* crnand */
e1571908 3754GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
79aceca5 3755/* crnor */
e1571908 3756GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
79aceca5 3757/* cror */
e1571908 3758GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
79aceca5 3759/* crorc */
e1571908 3760GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
79aceca5 3761/* crxor */
e1571908 3762GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
99e300ef 3763
54623277 3764/* mcrf */
99e300ef 3765static void gen_mcrf(DisasContext *ctx)
79aceca5 3766{
47e4661c 3767 tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
79aceca5
FB
3768}
3769
3770/*** System linkage ***/
99e300ef 3771
54623277 3772/* rfi (mem_idx only) */
99e300ef 3773static void gen_rfi(DisasContext *ctx)
79aceca5 3774{
9a64fbe4 3775#if defined(CONFIG_USER_ONLY)
e06fcd75 3776 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9a64fbe4
FB
3777#else
3778 /* Restore CPU state */
76db3ba4 3779 if (unlikely(!ctx->mem_idx)) {
e06fcd75 3780 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 3781 return;
9a64fbe4 3782 }
697ab892 3783 gen_update_cfar(ctx, ctx->nip);
e5f17ac6 3784 gen_helper_rfi(cpu_env);
e06fcd75 3785 gen_sync_exception(ctx);
9a64fbe4 3786#endif
79aceca5
FB
3787}
3788
426613db 3789#if defined(TARGET_PPC64)
99e300ef 3790static void gen_rfid(DisasContext *ctx)
426613db
JM
3791{
3792#if defined(CONFIG_USER_ONLY)
e06fcd75 3793 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db
JM
3794#else
3795 /* Restore CPU state */
76db3ba4 3796 if (unlikely(!ctx->mem_idx)) {
e06fcd75 3797 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db
JM
3798 return;
3799 }
697ab892 3800 gen_update_cfar(ctx, ctx->nip);
e5f17ac6 3801 gen_helper_rfid(cpu_env);
e06fcd75 3802 gen_sync_exception(ctx);
426613db
JM
3803#endif
3804}
426613db 3805
99e300ef 3806static void gen_hrfid(DisasContext *ctx)
be147d08
JM
3807{
3808#if defined(CONFIG_USER_ONLY)
e06fcd75 3809 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
3810#else
3811 /* Restore CPU state */
76db3ba4 3812 if (unlikely(ctx->mem_idx <= 1)) {
e06fcd75 3813 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
3814 return;
3815 }
e5f17ac6 3816 gen_helper_hrfid(cpu_env);
e06fcd75 3817 gen_sync_exception(ctx);
be147d08
JM
3818#endif
3819}
3820#endif
3821
79aceca5 3822/* sc */
417bf010
JM
3823#if defined(CONFIG_USER_ONLY)
3824#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3825#else
3826#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3827#endif
99e300ef 3828static void gen_sc(DisasContext *ctx)
79aceca5 3829{
e1833e1f
JM
3830 uint32_t lev;
3831
3832 lev = (ctx->opcode >> 5) & 0x7F;
e06fcd75 3833 gen_exception_err(ctx, POWERPC_SYSCALL, lev);
79aceca5
FB
3834}
3835
3836/*** Trap ***/
99e300ef 3837
54623277 3838/* tw */
99e300ef 3839static void gen_tw(DisasContext *ctx)
79aceca5 3840{
cab3bee2 3841 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
3842 /* Update the nip since this might generate a trap exception */
3843 gen_update_nip(ctx, ctx->nip);
e5f17ac6
BS
3844 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
3845 t0);
cab3bee2 3846 tcg_temp_free_i32(t0);
79aceca5
FB
3847}
3848
3849/* twi */
99e300ef 3850static void gen_twi(DisasContext *ctx)
79aceca5 3851{
cab3bee2
AJ
3852 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3853 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
3854 /* Update the nip since this might generate a trap exception */
3855 gen_update_nip(ctx, ctx->nip);
e5f17ac6 3856 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
cab3bee2
AJ
3857 tcg_temp_free(t0);
3858 tcg_temp_free_i32(t1);
79aceca5
FB
3859}
3860
d9bce9d9
JM
3861#if defined(TARGET_PPC64)
3862/* td */
99e300ef 3863static void gen_td(DisasContext *ctx)
d9bce9d9 3864{
cab3bee2 3865 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
3866 /* Update the nip since this might generate a trap exception */
3867 gen_update_nip(ctx, ctx->nip);
e5f17ac6
BS
3868 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
3869 t0);
cab3bee2 3870 tcg_temp_free_i32(t0);
d9bce9d9
JM
3871}
3872
3873/* tdi */
99e300ef 3874static void gen_tdi(DisasContext *ctx)
d9bce9d9 3875{
cab3bee2
AJ
3876 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3877 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
3878 /* Update the nip since this might generate a trap exception */
3879 gen_update_nip(ctx, ctx->nip);
e5f17ac6 3880 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
cab3bee2
AJ
3881 tcg_temp_free(t0);
3882 tcg_temp_free_i32(t1);
d9bce9d9
JM
3883}
3884#endif
3885
79aceca5 3886/*** Processor control ***/
99e300ef 3887
da91a00f
RH
3888static void gen_read_xer(TCGv dst)
3889{
3890 TCGv t0 = tcg_temp_new();
3891 TCGv t1 = tcg_temp_new();
3892 TCGv t2 = tcg_temp_new();
3893 tcg_gen_mov_tl(dst, cpu_xer);
3894 tcg_gen_shli_tl(t0, cpu_so, XER_SO);
3895 tcg_gen_shli_tl(t1, cpu_ov, XER_OV);
3896 tcg_gen_shli_tl(t2, cpu_ca, XER_CA);
3897 tcg_gen_or_tl(t0, t0, t1);
3898 tcg_gen_or_tl(dst, dst, t2);
3899 tcg_gen_or_tl(dst, dst, t0);
3900 tcg_temp_free(t0);
3901 tcg_temp_free(t1);
3902 tcg_temp_free(t2);
3903}
3904
3905static void gen_write_xer(TCGv src)
3906{
3907 tcg_gen_andi_tl(cpu_xer, src,
3908 ~((1u << XER_SO) | (1u << XER_OV) | (1u << XER_CA)));
3909 tcg_gen_shri_tl(cpu_so, src, XER_SO);
3910 tcg_gen_shri_tl(cpu_ov, src, XER_OV);
3911 tcg_gen_shri_tl(cpu_ca, src, XER_CA);
3912 tcg_gen_andi_tl(cpu_so, cpu_so, 1);
3913 tcg_gen_andi_tl(cpu_ov, cpu_ov, 1);
3914 tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
3915}
3916
54623277 3917/* mcrxr */
99e300ef 3918static void gen_mcrxr(DisasContext *ctx)
79aceca5 3919{
da91a00f
RH
3920 TCGv_i32 t0 = tcg_temp_new_i32();
3921 TCGv_i32 t1 = tcg_temp_new_i32();
3922 TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];
3923
3924 tcg_gen_trunc_tl_i32(t0, cpu_so);
3925 tcg_gen_trunc_tl_i32(t1, cpu_ov);
3926 tcg_gen_trunc_tl_i32(dst, cpu_ca);
3927 tcg_gen_shri_i32(t0, t0, 2);
3928 tcg_gen_shri_i32(t1, t1, 1);
3929 tcg_gen_or_i32(dst, dst, t0);
3930 tcg_gen_or_i32(dst, dst, t1);
3931 tcg_temp_free_i32(t0);
3932 tcg_temp_free_i32(t1);
3933
3934 tcg_gen_movi_tl(cpu_so, 0);
3935 tcg_gen_movi_tl(cpu_ov, 0);
3936 tcg_gen_movi_tl(cpu_ca, 0);
79aceca5
FB
3937}
3938
0cfe11ea 3939/* mfcr mfocrf */
99e300ef 3940static void gen_mfcr(DisasContext *ctx)
79aceca5 3941{
76a66253 3942 uint32_t crm, crn;
3b46e624 3943
76a66253
JM
3944 if (likely(ctx->opcode & 0x00100000)) {
3945 crm = CRM(ctx->opcode);
8dd640e4 3946 if (likely(crm && ((crm & (crm - 1)) == 0))) {
0cfe11ea 3947 crn = ctz32 (crm);
e1571908 3948 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
0497d2f4
AJ
3949 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
3950 cpu_gpr[rD(ctx->opcode)], crn * 4);
76a66253 3951 }
d9bce9d9 3952 } else {
651721b2
AJ
3953 TCGv_i32 t0 = tcg_temp_new_i32();
3954 tcg_gen_mov_i32(t0, cpu_crf[0]);
3955 tcg_gen_shli_i32(t0, t0, 4);
3956 tcg_gen_or_i32(t0, t0, cpu_crf[1]);
3957 tcg_gen_shli_i32(t0, t0, 4);
3958 tcg_gen_or_i32(t0, t0, cpu_crf[2]);
3959 tcg_gen_shli_i32(t0, t0, 4);
3960 tcg_gen_or_i32(t0, t0, cpu_crf[3]);
3961 tcg_gen_shli_i32(t0, t0, 4);
3962 tcg_gen_or_i32(t0, t0, cpu_crf[4]);
3963 tcg_gen_shli_i32(t0, t0, 4);
3964 tcg_gen_or_i32(t0, t0, cpu_crf[5]);
3965 tcg_gen_shli_i32(t0, t0, 4);
3966 tcg_gen_or_i32(t0, t0, cpu_crf[6]);
3967 tcg_gen_shli_i32(t0, t0, 4);
3968 tcg_gen_or_i32(t0, t0, cpu_crf[7]);
3969 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
3970 tcg_temp_free_i32(t0);
d9bce9d9 3971 }
79aceca5
FB
3972}
3973
3974/* mfmsr */
99e300ef 3975static void gen_mfmsr(DisasContext *ctx)
79aceca5 3976{
9a64fbe4 3977#if defined(CONFIG_USER_ONLY)
e06fcd75 3978 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 3979#else
76db3ba4 3980 if (unlikely(!ctx->mem_idx)) {
e06fcd75 3981 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 3982 return;
9a64fbe4 3983 }
6527f6ea 3984 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
9a64fbe4 3985#endif
79aceca5
FB
3986}
3987
7b13448f 3988static void spr_noaccess(void *opaque, int gprn, int sprn)
3fc6c082 3989{
7b13448f 3990#if 0
3fc6c082
FB
3991 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3992 printf("ERROR: try to access SPR %d !\n", sprn);
7b13448f 3993#endif
3fc6c082
FB
3994}
3995#define SPR_NOACCESS (&spr_noaccess)
3fc6c082 3996
79aceca5 3997/* mfspr */
636aa200 3998static inline void gen_op_mfspr(DisasContext *ctx)
79aceca5 3999{
45d827d2 4000 void (*read_cb)(void *opaque, int gprn, int sprn);
79aceca5
FB
4001 uint32_t sprn = SPR(ctx->opcode);
4002
3fc6c082 4003#if !defined(CONFIG_USER_ONLY)
76db3ba4 4004 if (ctx->mem_idx == 2)
be147d08 4005 read_cb = ctx->spr_cb[sprn].hea_read;
76db3ba4 4006 else if (ctx->mem_idx)
3fc6c082
FB
4007 read_cb = ctx->spr_cb[sprn].oea_read;
4008 else
9a64fbe4 4009#endif
3fc6c082 4010 read_cb = ctx->spr_cb[sprn].uea_read;
76a66253
JM
4011 if (likely(read_cb != NULL)) {
4012 if (likely(read_cb != SPR_NOACCESS)) {
45d827d2 4013 (*read_cb)(ctx, rD(ctx->opcode), sprn);
3fc6c082
FB
4014 } else {
4015 /* Privilege exception */
9fceefa7
JM
4016 /* This is a hack to avoid warnings when running Linux:
4017 * this OS breaks the PowerPC virtualisation model,
4018 * allowing userland application to read the PVR
4019 */
4020 if (sprn != SPR_PVR) {
c05541ee
AB
4021 qemu_log("Trying to read privileged spr %d (0x%03x) at "
4022 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4023 printf("Trying to read privileged spr %d (0x%03x) at "
4024 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
f24e5695 4025 }
e06fcd75 4026 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
79aceca5 4027 }
3fc6c082
FB
4028 } else {
4029 /* Not defined */
c05541ee
AB
4030 qemu_log("Trying to read invalid spr %d (0x%03x) at "
4031 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4032 printf("Trying to read invalid spr %d (0x%03x) at "
4033 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
e06fcd75 4034 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
79aceca5 4035 }
79aceca5
FB
4036}
4037
99e300ef 4038static void gen_mfspr(DisasContext *ctx)
79aceca5 4039{
3fc6c082 4040 gen_op_mfspr(ctx);
76a66253 4041}
3fc6c082
FB
4042
4043/* mftb */
99e300ef 4044static void gen_mftb(DisasContext *ctx)
3fc6c082
FB
4045{
4046 gen_op_mfspr(ctx);
79aceca5
FB
4047}
4048
0cfe11ea 4049/* mtcrf mtocrf*/
99e300ef 4050static void gen_mtcrf(DisasContext *ctx)
79aceca5 4051{
76a66253 4052 uint32_t crm, crn;
3b46e624 4053
76a66253 4054 crm = CRM(ctx->opcode);
8dd640e4 4055 if (likely((ctx->opcode & 0x00100000))) {
4056 if (crm && ((crm & (crm - 1)) == 0)) {
4057 TCGv_i32 temp = tcg_temp_new_i32();
0cfe11ea 4058 crn = ctz32 (crm);
8dd640e4 4059 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
0cfe11ea
AJ
4060 tcg_gen_shri_i32(temp, temp, crn * 4);
4061 tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
8dd640e4 4062 tcg_temp_free_i32(temp);
4063 }
76a66253 4064 } else {
651721b2
AJ
4065 TCGv_i32 temp = tcg_temp_new_i32();
4066 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
4067 for (crn = 0 ; crn < 8 ; crn++) {
4068 if (crm & (1 << crn)) {
4069 tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
4070 tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
4071 }
4072 }
a7812ae4 4073 tcg_temp_free_i32(temp);
76a66253 4074 }
79aceca5
FB
4075}
4076
4077/* mtmsr */
426613db 4078#if defined(TARGET_PPC64)
99e300ef 4079static void gen_mtmsrd(DisasContext *ctx)
426613db
JM
4080{
4081#if defined(CONFIG_USER_ONLY)
e06fcd75 4082 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
426613db 4083#else
76db3ba4 4084 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4085 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
426613db
JM
4086 return;
4087 }
be147d08
JM
4088 if (ctx->opcode & 0x00010000) {
4089 /* Special form that does not need any synchronisation */
6527f6ea
AJ
4090 TCGv t0 = tcg_temp_new();
4091 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
4092 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
4093 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
4094 tcg_temp_free(t0);
be147d08 4095 } else {
056b05f8
JM
4096 /* XXX: we need to update nip before the store
4097 * if we enter power saving mode, we will exit the loop
4098 * directly from ppc_store_msr
4099 */
be147d08 4100 gen_update_nip(ctx, ctx->nip);
e5f17ac6 4101 gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
be147d08
JM
4102 /* Must stop the translation as machine state (may have) changed */
4103 /* Note that mtmsr is not always defined as context-synchronizing */
e06fcd75 4104 gen_stop_exception(ctx);
be147d08 4105 }
426613db
JM
4106#endif
4107}
4108#endif
4109
99e300ef 4110static void gen_mtmsr(DisasContext *ctx)
79aceca5 4111{
9a64fbe4 4112#if defined(CONFIG_USER_ONLY)
e06fcd75 4113 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 4114#else
76db3ba4 4115 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4116 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 4117 return;
9a64fbe4 4118 }
be147d08
JM
4119 if (ctx->opcode & 0x00010000) {
4120 /* Special form that does not need any synchronisation */
6527f6ea
AJ
4121 TCGv t0 = tcg_temp_new();
4122 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
4123 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
4124 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
4125 tcg_temp_free(t0);
be147d08 4126 } else {
8018dc63
AG
4127 TCGv msr = tcg_temp_new();
4128
056b05f8
JM
4129 /* XXX: we need to update nip before the store
4130 * if we enter power saving mode, we will exit the loop
4131 * directly from ppc_store_msr
4132 */
be147d08 4133 gen_update_nip(ctx, ctx->nip);
d9bce9d9 4134#if defined(TARGET_PPC64)
8018dc63
AG
4135 tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
4136#else
4137 tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
d9bce9d9 4138#endif
e5f17ac6 4139 gen_helper_store_msr(cpu_env, msr);
be147d08 4140 /* Must stop the translation as machine state (may have) changed */
6527f6ea 4141 /* Note that mtmsr is not always defined as context-synchronizing */
e06fcd75 4142 gen_stop_exception(ctx);
be147d08 4143 }
9a64fbe4 4144#endif
79aceca5
FB
4145}
4146
4147/* mtspr */
99e300ef 4148static void gen_mtspr(DisasContext *ctx)
79aceca5 4149{
45d827d2 4150 void (*write_cb)(void *opaque, int sprn, int gprn);
79aceca5
FB
4151 uint32_t sprn = SPR(ctx->opcode);
4152
3fc6c082 4153#if !defined(CONFIG_USER_ONLY)
76db3ba4 4154 if (ctx->mem_idx == 2)
be147d08 4155 write_cb = ctx->spr_cb[sprn].hea_write;
76db3ba4 4156 else if (ctx->mem_idx)
3fc6c082
FB
4157 write_cb = ctx->spr_cb[sprn].oea_write;
4158 else
9a64fbe4 4159#endif
3fc6c082 4160 write_cb = ctx->spr_cb[sprn].uea_write;
76a66253
JM
4161 if (likely(write_cb != NULL)) {
4162 if (likely(write_cb != SPR_NOACCESS)) {
45d827d2 4163 (*write_cb)(ctx, sprn, rS(ctx->opcode));
3fc6c082
FB
4164 } else {
4165 /* Privilege exception */
c05541ee
AB
4166 qemu_log("Trying to write privileged spr %d (0x%03x) at "
4167 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4168 printf("Trying to write privileged spr %d (0x%03x) at "
4169 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
e06fcd75 4170 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253 4171 }
3fc6c082
FB
4172 } else {
4173 /* Not defined */
c05541ee
AB
4174 qemu_log("Trying to write invalid spr %d (0x%03x) at "
4175 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
4176 printf("Trying to write invalid spr %d (0x%03x) at "
4177 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
e06fcd75 4178 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
79aceca5 4179 }
79aceca5
FB
4180}
4181
4182/*** Cache management ***/
99e300ef 4183
54623277 4184/* dcbf */
99e300ef 4185static void gen_dcbf(DisasContext *ctx)
79aceca5 4186{
dac454af 4187 /* XXX: specification says this is treated as a load by the MMU */
76db3ba4
AJ
4188 TCGv t0;
4189 gen_set_access_type(ctx, ACCESS_CACHE);
4190 t0 = tcg_temp_new();
4191 gen_addr_reg_index(ctx, t0);
4192 gen_qemu_ld8u(ctx, t0, t0);
fea0c503 4193 tcg_temp_free(t0);
79aceca5
FB
4194}
4195
4196/* dcbi (Supervisor only) */
99e300ef 4197static void gen_dcbi(DisasContext *ctx)
79aceca5 4198{
a541f297 4199#if defined(CONFIG_USER_ONLY)
e06fcd75 4200 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a541f297 4201#else
b61f2753 4202 TCGv EA, val;
76db3ba4 4203 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4204 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 4205 return;
9a64fbe4 4206 }
a7812ae4 4207 EA = tcg_temp_new();
76db3ba4
AJ
4208 gen_set_access_type(ctx, ACCESS_CACHE);
4209 gen_addr_reg_index(ctx, EA);
a7812ae4 4210 val = tcg_temp_new();
76a66253 4211 /* XXX: specification says this should be treated as a store by the MMU */
76db3ba4
AJ
4212 gen_qemu_ld8u(ctx, val, EA);
4213 gen_qemu_st8(ctx, val, EA);
b61f2753
AJ
4214 tcg_temp_free(val);
4215 tcg_temp_free(EA);
a541f297 4216#endif
79aceca5
FB
4217}
4218
4219/* dcdst */
99e300ef 4220static void gen_dcbst(DisasContext *ctx)
79aceca5 4221{
76a66253 4222 /* XXX: specification say this is treated as a load by the MMU */
76db3ba4
AJ
4223 TCGv t0;
4224 gen_set_access_type(ctx, ACCESS_CACHE);
4225 t0 = tcg_temp_new();
4226 gen_addr_reg_index(ctx, t0);
4227 gen_qemu_ld8u(ctx, t0, t0);
fea0c503 4228 tcg_temp_free(t0);
79aceca5
FB
4229}
4230
4231/* dcbt */
99e300ef 4232static void gen_dcbt(DisasContext *ctx)
79aceca5 4233{
0db1b20e 4234 /* interpreted as no-op */
76a66253
JM
4235 /* XXX: specification say this is treated as a load by the MMU
4236 * but does not generate any exception
4237 */
79aceca5
FB
4238}
4239
4240/* dcbtst */
99e300ef 4241static void gen_dcbtst(DisasContext *ctx)
79aceca5 4242{
0db1b20e 4243 /* interpreted as no-op */
76a66253
JM
4244 /* XXX: specification say this is treated as a load by the MMU
4245 * but does not generate any exception
4246 */
79aceca5
FB
4247}
4248
4249/* dcbz */
99e300ef 4250static void gen_dcbz(DisasContext *ctx)
79aceca5 4251{
8e33944f
AG
4252 TCGv tcgv_addr;
4253 TCGv_i32 tcgv_is_dcbzl;
4254 int is_dcbzl = ctx->opcode & 0x00200000 ? 1 : 0;
d63001d1 4255
76db3ba4 4256 gen_set_access_type(ctx, ACCESS_CACHE);
799a8c8d
AJ
4257 /* NIP cannot be restored if the memory exception comes from an helper */
4258 gen_update_nip(ctx, ctx->nip - 4);
8e33944f
AG
4259 tcgv_addr = tcg_temp_new();
4260 tcgv_is_dcbzl = tcg_const_i32(is_dcbzl);
4261
4262 gen_addr_reg_index(ctx, tcgv_addr);
4263 gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_is_dcbzl);
4264
4265 tcg_temp_free(tcgv_addr);
4266 tcg_temp_free_i32(tcgv_is_dcbzl);
79aceca5
FB
4267}
4268
ae1c1a3d 4269/* dst / dstt */
99e300ef 4270static void gen_dst(DisasContext *ctx)
ae1c1a3d
AJ
4271{
4272 if (rA(ctx->opcode) == 0) {
4273 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4274 } else {
4275 /* interpreted as no-op */
4276 }
4277}
4278
4279/* dstst /dststt */
99e300ef 4280static void gen_dstst(DisasContext *ctx)
ae1c1a3d
AJ
4281{
4282 if (rA(ctx->opcode) == 0) {
4283 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4284 } else {
4285 /* interpreted as no-op */
4286 }
4287
4288}
4289
4290/* dss / dssall */
99e300ef 4291static void gen_dss(DisasContext *ctx)
ae1c1a3d
AJ
4292{
4293 /* interpreted as no-op */
4294}
4295
79aceca5 4296/* icbi */
99e300ef 4297static void gen_icbi(DisasContext *ctx)
79aceca5 4298{
76db3ba4
AJ
4299 TCGv t0;
4300 gen_set_access_type(ctx, ACCESS_CACHE);
30032c94
JM
4301 /* NIP cannot be restored if the memory exception comes from an helper */
4302 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
4303 t0 = tcg_temp_new();
4304 gen_addr_reg_index(ctx, t0);
2f5a189c 4305 gen_helper_icbi(cpu_env, t0);
37d269df 4306 tcg_temp_free(t0);
79aceca5
FB
4307}
4308
4309/* Optional: */
4310/* dcba */
99e300ef 4311static void gen_dcba(DisasContext *ctx)
79aceca5 4312{
0db1b20e
JM
4313 /* interpreted as no-op */
4314 /* XXX: specification say this is treated as a store by the MMU
4315 * but does not generate any exception
4316 */
79aceca5
FB
4317}
4318
4319/*** Segment register manipulation ***/
4320/* Supervisor only: */
99e300ef 4321
54623277 4322/* mfsr */
99e300ef 4323static void gen_mfsr(DisasContext *ctx)
79aceca5 4324{
9a64fbe4 4325#if defined(CONFIG_USER_ONLY)
e06fcd75 4326 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 4327#else
74d37793 4328 TCGv t0;
76db3ba4 4329 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4330 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 4331 return;
9a64fbe4 4332 }
74d37793 4333 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 4334 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 4335 tcg_temp_free(t0);
9a64fbe4 4336#endif
79aceca5
FB
4337}
4338
4339/* mfsrin */
99e300ef 4340static void gen_mfsrin(DisasContext *ctx)
79aceca5 4341{
9a64fbe4 4342#if defined(CONFIG_USER_ONLY)
e06fcd75 4343 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 4344#else
74d37793 4345 TCGv t0;
76db3ba4 4346 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4347 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 4348 return;
9a64fbe4 4349 }
74d37793
AJ
4350 t0 = tcg_temp_new();
4351 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4352 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 4353 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 4354 tcg_temp_free(t0);
9a64fbe4 4355#endif
79aceca5
FB
4356}
4357
4358/* mtsr */
99e300ef 4359static void gen_mtsr(DisasContext *ctx)
79aceca5 4360{
9a64fbe4 4361#if defined(CONFIG_USER_ONLY)
e06fcd75 4362 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 4363#else
74d37793 4364 TCGv t0;
76db3ba4 4365 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4366 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 4367 return;
9a64fbe4 4368 }
74d37793 4369 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 4370 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 4371 tcg_temp_free(t0);
9a64fbe4 4372#endif
79aceca5
FB
4373}
4374
4375/* mtsrin */
99e300ef 4376static void gen_mtsrin(DisasContext *ctx)
79aceca5 4377{
9a64fbe4 4378#if defined(CONFIG_USER_ONLY)
e06fcd75 4379 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 4380#else
74d37793 4381 TCGv t0;
76db3ba4 4382 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4383 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 4384 return;
9a64fbe4 4385 }
74d37793
AJ
4386 t0 = tcg_temp_new();
4387 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4388 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 4389 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
74d37793 4390 tcg_temp_free(t0);
9a64fbe4 4391#endif
79aceca5
FB
4392}
4393
12de9a39
JM
4394#if defined(TARGET_PPC64)
4395/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
e8eaa2c0 4396
54623277 4397/* mfsr */
e8eaa2c0 4398static void gen_mfsr_64b(DisasContext *ctx)
12de9a39
JM
4399{
4400#if defined(CONFIG_USER_ONLY)
e06fcd75 4401 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39 4402#else
74d37793 4403 TCGv t0;
76db3ba4 4404 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4405 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39
JM
4406 return;
4407 }
74d37793 4408 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 4409 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 4410 tcg_temp_free(t0);
12de9a39
JM
4411#endif
4412}
4413
4414/* mfsrin */
e8eaa2c0 4415static void gen_mfsrin_64b(DisasContext *ctx)
12de9a39
JM
4416{
4417#if defined(CONFIG_USER_ONLY)
e06fcd75 4418 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39 4419#else
74d37793 4420 TCGv t0;
76db3ba4 4421 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4422 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39
JM
4423 return;
4424 }
74d37793
AJ
4425 t0 = tcg_temp_new();
4426 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4427 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 4428 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 4429 tcg_temp_free(t0);
12de9a39
JM
4430#endif
4431}
4432
4433/* mtsr */
e8eaa2c0 4434static void gen_mtsr_64b(DisasContext *ctx)
12de9a39
JM
4435{
4436#if defined(CONFIG_USER_ONLY)
e06fcd75 4437 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39 4438#else
74d37793 4439 TCGv t0;
76db3ba4 4440 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4441 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39
JM
4442 return;
4443 }
74d37793 4444 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 4445 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 4446 tcg_temp_free(t0);
12de9a39
JM
4447#endif
4448}
4449
4450/* mtsrin */
e8eaa2c0 4451static void gen_mtsrin_64b(DisasContext *ctx)
12de9a39
JM
4452{
4453#if defined(CONFIG_USER_ONLY)
e06fcd75 4454 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39 4455#else
74d37793 4456 TCGv t0;
76db3ba4 4457 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4458 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39
JM
4459 return;
4460 }
74d37793
AJ
4461 t0 = tcg_temp_new();
4462 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4463 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 4464 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 4465 tcg_temp_free(t0);
12de9a39
JM
4466#endif
4467}
f6b868fc
BS
4468
4469/* slbmte */
e8eaa2c0 4470static void gen_slbmte(DisasContext *ctx)
f6b868fc
BS
4471{
4472#if defined(CONFIG_USER_ONLY)
4473 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4474#else
4475 if (unlikely(!ctx->mem_idx)) {
4476 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4477 return;
4478 }
c6c7cf05
BS
4479 gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)],
4480 cpu_gpr[rS(ctx->opcode)]);
f6b868fc
BS
4481#endif
4482}
4483
efdef95f
DG
4484static void gen_slbmfee(DisasContext *ctx)
4485{
4486#if defined(CONFIG_USER_ONLY)
4487 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4488#else
4489 if (unlikely(!ctx->mem_idx)) {
4490 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4491 return;
4492 }
c6c7cf05 4493 gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env,
efdef95f
DG
4494 cpu_gpr[rB(ctx->opcode)]);
4495#endif
4496}
4497
4498static void gen_slbmfev(DisasContext *ctx)
4499{
4500#if defined(CONFIG_USER_ONLY)
4501 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4502#else
4503 if (unlikely(!ctx->mem_idx)) {
4504 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4505 return;
4506 }
c6c7cf05 4507 gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
efdef95f
DG
4508 cpu_gpr[rB(ctx->opcode)]);
4509#endif
4510}
12de9a39
JM
4511#endif /* defined(TARGET_PPC64) */
4512
79aceca5 4513/*** Lookaside buffer management ***/
76db3ba4 4514/* Optional & mem_idx only: */
99e300ef 4515
54623277 4516/* tlbia */
99e300ef 4517static void gen_tlbia(DisasContext *ctx)
79aceca5 4518{
9a64fbe4 4519#if defined(CONFIG_USER_ONLY)
e06fcd75 4520 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9a64fbe4 4521#else
76db3ba4 4522 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4523 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 4524 return;
9a64fbe4 4525 }
c6c7cf05 4526 gen_helper_tlbia(cpu_env);
9a64fbe4 4527#endif
79aceca5
FB
4528}
4529
bf14b1ce 4530/* tlbiel */
99e300ef 4531static void gen_tlbiel(DisasContext *ctx)
bf14b1ce
BS
4532{
4533#if defined(CONFIG_USER_ONLY)
4534 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4535#else
4536 if (unlikely(!ctx->mem_idx)) {
4537 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4538 return;
4539 }
c6c7cf05 4540 gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
bf14b1ce
BS
4541#endif
4542}
4543
79aceca5 4544/* tlbie */
99e300ef 4545static void gen_tlbie(DisasContext *ctx)
79aceca5 4546{
9a64fbe4 4547#if defined(CONFIG_USER_ONLY)
e06fcd75 4548 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9a64fbe4 4549#else
76db3ba4 4550 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4551 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 4552 return;
9a64fbe4 4553 }
9ca3f7f3 4554 if (NARROW_MODE(ctx)) {
74d37793
AJ
4555 TCGv t0 = tcg_temp_new();
4556 tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
c6c7cf05 4557 gen_helper_tlbie(cpu_env, t0);
74d37793 4558 tcg_temp_free(t0);
9ca3f7f3 4559 } else {
c6c7cf05 4560 gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9ca3f7f3 4561 }
9a64fbe4 4562#endif
79aceca5
FB
4563}
4564
4565/* tlbsync */
99e300ef 4566static void gen_tlbsync(DisasContext *ctx)
79aceca5 4567{
9a64fbe4 4568#if defined(CONFIG_USER_ONLY)
e06fcd75 4569 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9a64fbe4 4570#else
76db3ba4 4571 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4572 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 4573 return;
9a64fbe4
FB
4574 }
4575 /* This has no effect: it should ensure that all previous
4576 * tlbie have completed
4577 */
e06fcd75 4578 gen_stop_exception(ctx);
9a64fbe4 4579#endif
79aceca5
FB
4580}
4581
426613db
JM
4582#if defined(TARGET_PPC64)
4583/* slbia */
99e300ef 4584static void gen_slbia(DisasContext *ctx)
426613db
JM
4585{
4586#if defined(CONFIG_USER_ONLY)
e06fcd75 4587 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db 4588#else
76db3ba4 4589 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4590 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db
JM
4591 return;
4592 }
c6c7cf05 4593 gen_helper_slbia(cpu_env);
426613db
JM
4594#endif
4595}
4596
4597/* slbie */
99e300ef 4598static void gen_slbie(DisasContext *ctx)
426613db
JM
4599{
4600#if defined(CONFIG_USER_ONLY)
e06fcd75 4601 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db 4602#else
76db3ba4 4603 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4604 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db
JM
4605 return;
4606 }
c6c7cf05 4607 gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
426613db
JM
4608#endif
4609}
4610#endif
4611
79aceca5
FB
4612/*** External control ***/
4613/* Optional: */
99e300ef 4614
54623277 4615/* eciwx */
99e300ef 4616static void gen_eciwx(DisasContext *ctx)
79aceca5 4617{
76db3ba4 4618 TCGv t0;
fa407c03 4619 /* Should check EAR[E] ! */
76db3ba4
AJ
4620 gen_set_access_type(ctx, ACCESS_EXT);
4621 t0 = tcg_temp_new();
4622 gen_addr_reg_index(ctx, t0);
fa407c03 4623 gen_check_align(ctx, t0, 0x03);
76db3ba4 4624 gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
fa407c03 4625 tcg_temp_free(t0);
76a66253
JM
4626}
4627
4628/* ecowx */
99e300ef 4629static void gen_ecowx(DisasContext *ctx)
76a66253 4630{
76db3ba4 4631 TCGv t0;
fa407c03 4632 /* Should check EAR[E] ! */
76db3ba4
AJ
4633 gen_set_access_type(ctx, ACCESS_EXT);
4634 t0 = tcg_temp_new();
4635 gen_addr_reg_index(ctx, t0);
fa407c03 4636 gen_check_align(ctx, t0, 0x03);
76db3ba4 4637 gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
fa407c03 4638 tcg_temp_free(t0);
76a66253
JM
4639}
4640
4641/* PowerPC 601 specific instructions */
99e300ef 4642
54623277 4643/* abs - abs. */
99e300ef 4644static void gen_abs(DisasContext *ctx)
76a66253 4645{
22e0e173
AJ
4646 int l1 = gen_new_label();
4647 int l2 = gen_new_label();
4648 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4649 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4650 tcg_gen_br(l2);
4651 gen_set_label(l1);
4652 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4653 gen_set_label(l2);
76a66253 4654 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4655 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4656}
4657
4658/* abso - abso. */
99e300ef 4659static void gen_abso(DisasContext *ctx)
76a66253 4660{
22e0e173
AJ
4661 int l1 = gen_new_label();
4662 int l2 = gen_new_label();
4663 int l3 = gen_new_label();
4664 /* Start with XER OV disabled, the most likely case */
da91a00f 4665 tcg_gen_movi_tl(cpu_ov, 0);
22e0e173
AJ
4666 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4667 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
da91a00f
RH
4668 tcg_gen_movi_tl(cpu_ov, 1);
4669 tcg_gen_movi_tl(cpu_so, 1);
22e0e173
AJ
4670 tcg_gen_br(l2);
4671 gen_set_label(l1);
4672 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4673 tcg_gen_br(l3);
4674 gen_set_label(l2);
4675 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4676 gen_set_label(l3);
76a66253 4677 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4678 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4679}
4680
4681/* clcs */
99e300ef 4682static void gen_clcs(DisasContext *ctx)
76a66253 4683{
22e0e173 4684 TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
d523dd00 4685 gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
22e0e173 4686 tcg_temp_free_i32(t0);
c7697e1f 4687 /* Rc=1 sets CR0 to an undefined state */
76a66253
JM
4688}
4689
4690/* div - div. */
99e300ef 4691static void gen_div(DisasContext *ctx)
76a66253 4692{
d15f74fb
BS
4693 gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
4694 cpu_gpr[rB(ctx->opcode)]);
76a66253 4695 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4696 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4697}
4698
4699/* divo - divo. */
99e300ef 4700static void gen_divo(DisasContext *ctx)
76a66253 4701{
d15f74fb
BS
4702 gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
4703 cpu_gpr[rB(ctx->opcode)]);
76a66253 4704 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4705 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4706}
4707
4708/* divs - divs. */
99e300ef 4709static void gen_divs(DisasContext *ctx)
76a66253 4710{
d15f74fb
BS
4711 gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
4712 cpu_gpr[rB(ctx->opcode)]);
76a66253 4713 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4714 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4715}
4716
4717/* divso - divso. */
99e300ef 4718static void gen_divso(DisasContext *ctx)
76a66253 4719{
d15f74fb
BS
4720 gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
4721 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 4722 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4723 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4724}
4725
4726/* doz - doz. */
99e300ef 4727static void gen_doz(DisasContext *ctx)
76a66253 4728{
22e0e173
AJ
4729 int l1 = gen_new_label();
4730 int l2 = gen_new_label();
4731 tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4732 tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4733 tcg_gen_br(l2);
4734 gen_set_label(l1);
4735 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4736 gen_set_label(l2);
76a66253 4737 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4738 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4739}
4740
4741/* dozo - dozo. */
99e300ef 4742static void gen_dozo(DisasContext *ctx)
76a66253 4743{
22e0e173
AJ
4744 int l1 = gen_new_label();
4745 int l2 = gen_new_label();
4746 TCGv t0 = tcg_temp_new();
4747 TCGv t1 = tcg_temp_new();
4748 TCGv t2 = tcg_temp_new();
4749 /* Start with XER OV disabled, the most likely case */
da91a00f 4750 tcg_gen_movi_tl(cpu_ov, 0);
22e0e173
AJ
4751 tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4752 tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4753 tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4754 tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4755 tcg_gen_andc_tl(t1, t1, t2);
4756 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4757 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
da91a00f
RH
4758 tcg_gen_movi_tl(cpu_ov, 1);
4759 tcg_gen_movi_tl(cpu_so, 1);
22e0e173
AJ
4760 tcg_gen_br(l2);
4761 gen_set_label(l1);
4762 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4763 gen_set_label(l2);
4764 tcg_temp_free(t0);
4765 tcg_temp_free(t1);
4766 tcg_temp_free(t2);
76a66253 4767 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4768 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4769}
4770
4771/* dozi */
99e300ef 4772static void gen_dozi(DisasContext *ctx)
76a66253 4773{
22e0e173
AJ
4774 target_long simm = SIMM(ctx->opcode);
4775 int l1 = gen_new_label();
4776 int l2 = gen_new_label();
4777 tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4778 tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4779 tcg_gen_br(l2);
4780 gen_set_label(l1);
4781 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4782 gen_set_label(l2);
4783 if (unlikely(Rc(ctx->opcode) != 0))
4784 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4785}
4786
76a66253 4787/* lscbx - lscbx. */
99e300ef 4788static void gen_lscbx(DisasContext *ctx)
76a66253 4789{
bdb4b689
AJ
4790 TCGv t0 = tcg_temp_new();
4791 TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4792 TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4793 TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
76a66253 4794
76db3ba4 4795 gen_addr_reg_index(ctx, t0);
76a66253 4796 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4797 gen_update_nip(ctx, ctx->nip - 4);
2f5a189c 4798 gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
bdb4b689
AJ
4799 tcg_temp_free_i32(t1);
4800 tcg_temp_free_i32(t2);
4801 tcg_temp_free_i32(t3);
3d7b417e 4802 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
bdb4b689 4803 tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
76a66253 4804 if (unlikely(Rc(ctx->opcode) != 0))
bdb4b689
AJ
4805 gen_set_Rc0(ctx, t0);
4806 tcg_temp_free(t0);
76a66253
JM
4807}
4808
4809/* maskg - maskg. */
99e300ef 4810static void gen_maskg(DisasContext *ctx)
76a66253 4811{
22e0e173
AJ
4812 int l1 = gen_new_label();
4813 TCGv t0 = tcg_temp_new();
4814 TCGv t1 = tcg_temp_new();
4815 TCGv t2 = tcg_temp_new();
4816 TCGv t3 = tcg_temp_new();
4817 tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4818 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4819 tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4820 tcg_gen_addi_tl(t2, t0, 1);
4821 tcg_gen_shr_tl(t2, t3, t2);
4822 tcg_gen_shr_tl(t3, t3, t1);
4823 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4824 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4825 tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4826 gen_set_label(l1);
4827 tcg_temp_free(t0);
4828 tcg_temp_free(t1);
4829 tcg_temp_free(t2);
4830 tcg_temp_free(t3);
76a66253 4831 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4832 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4833}
4834
4835/* maskir - maskir. */
99e300ef 4836static void gen_maskir(DisasContext *ctx)
76a66253 4837{
22e0e173
AJ
4838 TCGv t0 = tcg_temp_new();
4839 TCGv t1 = tcg_temp_new();
4840 tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4841 tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4842 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4843 tcg_temp_free(t0);
4844 tcg_temp_free(t1);
76a66253 4845 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4846 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4847}
4848
4849/* mul - mul. */
99e300ef 4850static void gen_mul(DisasContext *ctx)
76a66253 4851{
22e0e173
AJ
4852 TCGv_i64 t0 = tcg_temp_new_i64();
4853 TCGv_i64 t1 = tcg_temp_new_i64();
4854 TCGv t2 = tcg_temp_new();
4855 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4856 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4857 tcg_gen_mul_i64(t0, t0, t1);
4858 tcg_gen_trunc_i64_tl(t2, t0);
4859 gen_store_spr(SPR_MQ, t2);
4860 tcg_gen_shri_i64(t1, t0, 32);
4861 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4862 tcg_temp_free_i64(t0);
4863 tcg_temp_free_i64(t1);
4864 tcg_temp_free(t2);
76a66253 4865 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4866 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4867}
4868
4869/* mulo - mulo. */
99e300ef 4870static void gen_mulo(DisasContext *ctx)
76a66253 4871{
22e0e173
AJ
4872 int l1 = gen_new_label();
4873 TCGv_i64 t0 = tcg_temp_new_i64();
4874 TCGv_i64 t1 = tcg_temp_new_i64();
4875 TCGv t2 = tcg_temp_new();
4876 /* Start with XER OV disabled, the most likely case */
da91a00f 4877 tcg_gen_movi_tl(cpu_ov, 0);
22e0e173
AJ
4878 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4879 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4880 tcg_gen_mul_i64(t0, t0, t1);
4881 tcg_gen_trunc_i64_tl(t2, t0);
4882 gen_store_spr(SPR_MQ, t2);
4883 tcg_gen_shri_i64(t1, t0, 32);
4884 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4885 tcg_gen_ext32s_i64(t1, t0);
4886 tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
da91a00f
RH
4887 tcg_gen_movi_tl(cpu_ov, 1);
4888 tcg_gen_movi_tl(cpu_so, 1);
22e0e173
AJ
4889 gen_set_label(l1);
4890 tcg_temp_free_i64(t0);
4891 tcg_temp_free_i64(t1);
4892 tcg_temp_free(t2);
76a66253 4893 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4894 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4895}
4896
4897/* nabs - nabs. */
99e300ef 4898static void gen_nabs(DisasContext *ctx)
76a66253 4899{
22e0e173
AJ
4900 int l1 = gen_new_label();
4901 int l2 = gen_new_label();
4902 tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4903 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4904 tcg_gen_br(l2);
4905 gen_set_label(l1);
4906 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4907 gen_set_label(l2);
76a66253 4908 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4909 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4910}
4911
4912/* nabso - nabso. */
99e300ef 4913static void gen_nabso(DisasContext *ctx)
76a66253 4914{
22e0e173
AJ
4915 int l1 = gen_new_label();
4916 int l2 = gen_new_label();
4917 tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4918 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4919 tcg_gen_br(l2);
4920 gen_set_label(l1);
4921 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4922 gen_set_label(l2);
4923 /* nabs never overflows */
da91a00f 4924 tcg_gen_movi_tl(cpu_ov, 0);
76a66253 4925 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4926 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4927}
4928
4929/* rlmi - rlmi. */
99e300ef 4930static void gen_rlmi(DisasContext *ctx)
76a66253 4931{
7487953d
AJ
4932 uint32_t mb = MB(ctx->opcode);
4933 uint32_t me = ME(ctx->opcode);
4934 TCGv t0 = tcg_temp_new();
4935 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4936 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4937 tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4938 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4939 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4940 tcg_temp_free(t0);
76a66253 4941 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4942 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4943}
4944
4945/* rrib - rrib. */
99e300ef 4946static void gen_rrib(DisasContext *ctx)
76a66253 4947{
7487953d
AJ
4948 TCGv t0 = tcg_temp_new();
4949 TCGv t1 = tcg_temp_new();
4950 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4951 tcg_gen_movi_tl(t1, 0x80000000);
4952 tcg_gen_shr_tl(t1, t1, t0);
4953 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4954 tcg_gen_and_tl(t0, t0, t1);
4955 tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4956 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4957 tcg_temp_free(t0);
4958 tcg_temp_free(t1);
76a66253 4959 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4960 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4961}
4962
4963/* sle - sle. */
99e300ef 4964static void gen_sle(DisasContext *ctx)
76a66253 4965{
7487953d
AJ
4966 TCGv t0 = tcg_temp_new();
4967 TCGv t1 = tcg_temp_new();
4968 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4969 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4970 tcg_gen_subfi_tl(t1, 32, t1);
4971 tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4972 tcg_gen_or_tl(t1, t0, t1);
4973 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4974 gen_store_spr(SPR_MQ, t1);
4975 tcg_temp_free(t0);
4976 tcg_temp_free(t1);
76a66253 4977 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4978 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4979}
4980
4981/* sleq - sleq. */
99e300ef 4982static void gen_sleq(DisasContext *ctx)
76a66253 4983{
7487953d
AJ
4984 TCGv t0 = tcg_temp_new();
4985 TCGv t1 = tcg_temp_new();
4986 TCGv t2 = tcg_temp_new();
4987 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4988 tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4989 tcg_gen_shl_tl(t2, t2, t0);
4990 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4991 gen_load_spr(t1, SPR_MQ);
4992 gen_store_spr(SPR_MQ, t0);
4993 tcg_gen_and_tl(t0, t0, t2);
4994 tcg_gen_andc_tl(t1, t1, t2);
4995 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4996 tcg_temp_free(t0);
4997 tcg_temp_free(t1);
4998 tcg_temp_free(t2);
76a66253 4999 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5000 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5001}
5002
5003/* sliq - sliq. */
99e300ef 5004static void gen_sliq(DisasContext *ctx)
76a66253 5005{
7487953d
AJ
5006 int sh = SH(ctx->opcode);
5007 TCGv t0 = tcg_temp_new();
5008 TCGv t1 = tcg_temp_new();
5009 tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5010 tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5011 tcg_gen_or_tl(t1, t0, t1);
5012 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5013 gen_store_spr(SPR_MQ, t1);
5014 tcg_temp_free(t0);
5015 tcg_temp_free(t1);
76a66253 5016 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5017 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5018}
5019
5020/* slliq - slliq. */
99e300ef 5021static void gen_slliq(DisasContext *ctx)
76a66253 5022{
7487953d
AJ
5023 int sh = SH(ctx->opcode);
5024 TCGv t0 = tcg_temp_new();
5025 TCGv t1 = tcg_temp_new();
5026 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5027 gen_load_spr(t1, SPR_MQ);
5028 gen_store_spr(SPR_MQ, t0);
5029 tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh));
5030 tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
5031 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5032 tcg_temp_free(t0);
5033 tcg_temp_free(t1);
76a66253 5034 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5035 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5036}
5037
5038/* sllq - sllq. */
99e300ef 5039static void gen_sllq(DisasContext *ctx)
76a66253 5040{
7487953d
AJ
5041 int l1 = gen_new_label();
5042 int l2 = gen_new_label();
5043 TCGv t0 = tcg_temp_local_new();
5044 TCGv t1 = tcg_temp_local_new();
5045 TCGv t2 = tcg_temp_local_new();
5046 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5047 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5048 tcg_gen_shl_tl(t1, t1, t2);
5049 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5050 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5051 gen_load_spr(t0, SPR_MQ);
5052 tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5053 tcg_gen_br(l2);
5054 gen_set_label(l1);
5055 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5056 gen_load_spr(t2, SPR_MQ);
5057 tcg_gen_andc_tl(t1, t2, t1);
5058 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5059 gen_set_label(l2);
5060 tcg_temp_free(t0);
5061 tcg_temp_free(t1);
5062 tcg_temp_free(t2);
76a66253 5063 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5064 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5065}
5066
5067/* slq - slq. */
99e300ef 5068static void gen_slq(DisasContext *ctx)
76a66253 5069{
7487953d
AJ
5070 int l1 = gen_new_label();
5071 TCGv t0 = tcg_temp_new();
5072 TCGv t1 = tcg_temp_new();
5073 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5074 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5075 tcg_gen_subfi_tl(t1, 32, t1);
5076 tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5077 tcg_gen_or_tl(t1, t0, t1);
5078 gen_store_spr(SPR_MQ, t1);
5079 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5080 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5081 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5082 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5083 gen_set_label(l1);
5084 tcg_temp_free(t0);
5085 tcg_temp_free(t1);
76a66253 5086 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5087 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5088}
5089
d9bce9d9 5090/* sraiq - sraiq. */
99e300ef 5091static void gen_sraiq(DisasContext *ctx)
76a66253 5092{
7487953d
AJ
5093 int sh = SH(ctx->opcode);
5094 int l1 = gen_new_label();
5095 TCGv t0 = tcg_temp_new();
5096 TCGv t1 = tcg_temp_new();
5097 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5098 tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5099 tcg_gen_or_tl(t0, t0, t1);
5100 gen_store_spr(SPR_MQ, t0);
da91a00f 5101 tcg_gen_movi_tl(cpu_ca, 0);
7487953d
AJ
5102 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5103 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
da91a00f 5104 tcg_gen_movi_tl(cpu_ca, 1);
7487953d
AJ
5105 gen_set_label(l1);
5106 tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
5107 tcg_temp_free(t0);
5108 tcg_temp_free(t1);
76a66253 5109 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5110 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5111}
5112
5113/* sraq - sraq. */
99e300ef 5114static void gen_sraq(DisasContext *ctx)
76a66253 5115{
7487953d
AJ
5116 int l1 = gen_new_label();
5117 int l2 = gen_new_label();
5118 TCGv t0 = tcg_temp_new();
5119 TCGv t1 = tcg_temp_local_new();
5120 TCGv t2 = tcg_temp_local_new();
5121 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5122 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5123 tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
5124 tcg_gen_subfi_tl(t2, 32, t2);
5125 tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
5126 tcg_gen_or_tl(t0, t0, t2);
5127 gen_store_spr(SPR_MQ, t0);
5128 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5129 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
5130 tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
5131 tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
5132 gen_set_label(l1);
5133 tcg_temp_free(t0);
5134 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
da91a00f 5135 tcg_gen_movi_tl(cpu_ca, 0);
7487953d
AJ
5136 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
5137 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
da91a00f 5138 tcg_gen_movi_tl(cpu_ca, 1);
7487953d
AJ
5139 gen_set_label(l2);
5140 tcg_temp_free(t1);
5141 tcg_temp_free(t2);
76a66253 5142 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5143 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5144}
5145
5146/* sre - sre. */
99e300ef 5147static void gen_sre(DisasContext *ctx)
76a66253 5148{
7487953d
AJ
5149 TCGv t0 = tcg_temp_new();
5150 TCGv t1 = tcg_temp_new();
5151 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5152 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5153 tcg_gen_subfi_tl(t1, 32, t1);
5154 tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5155 tcg_gen_or_tl(t1, t0, t1);
5156 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5157 gen_store_spr(SPR_MQ, t1);
5158 tcg_temp_free(t0);
5159 tcg_temp_free(t1);
76a66253 5160 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5161 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5162}
5163
5164/* srea - srea. */
99e300ef 5165static void gen_srea(DisasContext *ctx)
76a66253 5166{
7487953d
AJ
5167 TCGv t0 = tcg_temp_new();
5168 TCGv t1 = tcg_temp_new();
5169 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5170 tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5171 gen_store_spr(SPR_MQ, t0);
5172 tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
5173 tcg_temp_free(t0);
5174 tcg_temp_free(t1);
76a66253 5175 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5176 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5177}
5178
5179/* sreq */
99e300ef 5180static void gen_sreq(DisasContext *ctx)
76a66253 5181{
7487953d
AJ
5182 TCGv t0 = tcg_temp_new();
5183 TCGv t1 = tcg_temp_new();
5184 TCGv t2 = tcg_temp_new();
5185 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
5186 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5187 tcg_gen_shr_tl(t1, t1, t0);
5188 tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
5189 gen_load_spr(t2, SPR_MQ);
5190 gen_store_spr(SPR_MQ, t0);
5191 tcg_gen_and_tl(t0, t0, t1);
5192 tcg_gen_andc_tl(t2, t2, t1);
5193 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5194 tcg_temp_free(t0);
5195 tcg_temp_free(t1);
5196 tcg_temp_free(t2);
76a66253 5197 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5198 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5199}
5200
5201/* sriq */
99e300ef 5202static void gen_sriq(DisasContext *ctx)
76a66253 5203{
7487953d
AJ
5204 int sh = SH(ctx->opcode);
5205 TCGv t0 = tcg_temp_new();
5206 TCGv t1 = tcg_temp_new();
5207 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5208 tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5209 tcg_gen_or_tl(t1, t0, t1);
5210 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5211 gen_store_spr(SPR_MQ, t1);
5212 tcg_temp_free(t0);
5213 tcg_temp_free(t1);
76a66253 5214 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5215 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5216}
5217
5218/* srliq */
99e300ef 5219static void gen_srliq(DisasContext *ctx)
76a66253 5220{
7487953d
AJ
5221 int sh = SH(ctx->opcode);
5222 TCGv t0 = tcg_temp_new();
5223 TCGv t1 = tcg_temp_new();
5224 tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5225 gen_load_spr(t1, SPR_MQ);
5226 gen_store_spr(SPR_MQ, t0);
5227 tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh));
5228 tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
5229 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5230 tcg_temp_free(t0);
5231 tcg_temp_free(t1);
76a66253 5232 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5233 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5234}
5235
5236/* srlq */
99e300ef 5237static void gen_srlq(DisasContext *ctx)
76a66253 5238{
7487953d
AJ
5239 int l1 = gen_new_label();
5240 int l2 = gen_new_label();
5241 TCGv t0 = tcg_temp_local_new();
5242 TCGv t1 = tcg_temp_local_new();
5243 TCGv t2 = tcg_temp_local_new();
5244 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5245 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5246 tcg_gen_shr_tl(t2, t1, t2);
5247 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5248 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5249 gen_load_spr(t0, SPR_MQ);
5250 tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5251 tcg_gen_br(l2);
5252 gen_set_label(l1);
5253 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5254 tcg_gen_and_tl(t0, t0, t2);
5255 gen_load_spr(t1, SPR_MQ);
5256 tcg_gen_andc_tl(t1, t1, t2);
5257 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5258 gen_set_label(l2);
5259 tcg_temp_free(t0);
5260 tcg_temp_free(t1);
5261 tcg_temp_free(t2);
76a66253 5262 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5263 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5264}
5265
5266/* srq */
99e300ef 5267static void gen_srq(DisasContext *ctx)
76a66253 5268{
7487953d
AJ
5269 int l1 = gen_new_label();
5270 TCGv t0 = tcg_temp_new();
5271 TCGv t1 = tcg_temp_new();
5272 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5273 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5274 tcg_gen_subfi_tl(t1, 32, t1);
5275 tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5276 tcg_gen_or_tl(t1, t0, t1);
5277 gen_store_spr(SPR_MQ, t1);
5278 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5279 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5280 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5281 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5282 gen_set_label(l1);
5283 tcg_temp_free(t0);
5284 tcg_temp_free(t1);
76a66253 5285 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5286 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5287}
5288
5289/* PowerPC 602 specific instructions */
99e300ef 5290
54623277 5291/* dsa */
99e300ef 5292static void gen_dsa(DisasContext *ctx)
76a66253
JM
5293{
5294 /* XXX: TODO */
e06fcd75 5295 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5296}
5297
5298/* esa */
99e300ef 5299static void gen_esa(DisasContext *ctx)
76a66253
JM
5300{
5301 /* XXX: TODO */
e06fcd75 5302 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5303}
5304
5305/* mfrom */
99e300ef 5306static void gen_mfrom(DisasContext *ctx)
76a66253
JM
5307{
5308#if defined(CONFIG_USER_ONLY)
e06fcd75 5309 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5310#else
76db3ba4 5311 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5312 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5313 return;
5314 }
cf02a65c 5315 gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5316#endif
5317}
5318
5319/* 602 - 603 - G2 TLB management */
e8eaa2c0 5320
54623277 5321/* tlbld */
e8eaa2c0 5322static void gen_tlbld_6xx(DisasContext *ctx)
76a66253
JM
5323{
5324#if defined(CONFIG_USER_ONLY)
e06fcd75 5325 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5326#else
76db3ba4 5327 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5328 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5329 return;
5330 }
c6c7cf05 5331 gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
5332#endif
5333}
5334
5335/* tlbli */
e8eaa2c0 5336static void gen_tlbli_6xx(DisasContext *ctx)
76a66253
JM
5337{
5338#if defined(CONFIG_USER_ONLY)
e06fcd75 5339 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5340#else
76db3ba4 5341 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5342 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5343 return;
5344 }
c6c7cf05 5345 gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
5346#endif
5347}
5348
7dbe11ac 5349/* 74xx TLB management */
e8eaa2c0 5350
54623277 5351/* tlbld */
e8eaa2c0 5352static void gen_tlbld_74xx(DisasContext *ctx)
7dbe11ac
JM
5353{
5354#if defined(CONFIG_USER_ONLY)
e06fcd75 5355 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
7dbe11ac 5356#else
76db3ba4 5357 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5358 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
7dbe11ac
JM
5359 return;
5360 }
c6c7cf05 5361 gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
5362#endif
5363}
5364
5365/* tlbli */
e8eaa2c0 5366static void gen_tlbli_74xx(DisasContext *ctx)
7dbe11ac
JM
5367{
5368#if defined(CONFIG_USER_ONLY)
e06fcd75 5369 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
7dbe11ac 5370#else
76db3ba4 5371 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5372 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
7dbe11ac
JM
5373 return;
5374 }
c6c7cf05 5375 gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
5376#endif
5377}
5378
76a66253 5379/* POWER instructions not in PowerPC 601 */
99e300ef 5380
54623277 5381/* clf */
99e300ef 5382static void gen_clf(DisasContext *ctx)
76a66253
JM
5383{
5384 /* Cache line flush: implemented as no-op */
5385}
5386
5387/* cli */
99e300ef 5388static void gen_cli(DisasContext *ctx)
76a66253 5389{
7f75ffd3 5390 /* Cache line invalidate: privileged and treated as no-op */
76a66253 5391#if defined(CONFIG_USER_ONLY)
e06fcd75 5392 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5393#else
76db3ba4 5394 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5395 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5396 return;
5397 }
5398#endif
5399}
5400
5401/* dclst */
99e300ef 5402static void gen_dclst(DisasContext *ctx)
76a66253
JM
5403{
5404 /* Data cache line store: treated as no-op */
5405}
5406
99e300ef 5407static void gen_mfsri(DisasContext *ctx)
76a66253
JM
5408{
5409#if defined(CONFIG_USER_ONLY)
e06fcd75 5410 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5411#else
74d37793
AJ
5412 int ra = rA(ctx->opcode);
5413 int rd = rD(ctx->opcode);
5414 TCGv t0;
76db3ba4 5415 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5416 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5417 return;
5418 }
74d37793 5419 t0 = tcg_temp_new();
76db3ba4 5420 gen_addr_reg_index(ctx, t0);
74d37793
AJ
5421 tcg_gen_shri_tl(t0, t0, 28);
5422 tcg_gen_andi_tl(t0, t0, 0xF);
c6c7cf05 5423 gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
74d37793 5424 tcg_temp_free(t0);
76a66253 5425 if (ra != 0 && ra != rd)
74d37793 5426 tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
76a66253
JM
5427#endif
5428}
5429
99e300ef 5430static void gen_rac(DisasContext *ctx)
76a66253
JM
5431{
5432#if defined(CONFIG_USER_ONLY)
e06fcd75 5433 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5434#else
22e0e173 5435 TCGv t0;
76db3ba4 5436 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5437 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5438 return;
5439 }
22e0e173 5440 t0 = tcg_temp_new();
76db3ba4 5441 gen_addr_reg_index(ctx, t0);
c6c7cf05 5442 gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
22e0e173 5443 tcg_temp_free(t0);
76a66253
JM
5444#endif
5445}
5446
99e300ef 5447static void gen_rfsvc(DisasContext *ctx)
76a66253
JM
5448{
5449#if defined(CONFIG_USER_ONLY)
e06fcd75 5450 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5451#else
76db3ba4 5452 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5453 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5454 return;
5455 }
e5f17ac6 5456 gen_helper_rfsvc(cpu_env);
e06fcd75 5457 gen_sync_exception(ctx);
76a66253
JM
5458#endif
5459}
5460
5461/* svc is not implemented for now */
5462
5463/* POWER2 specific instructions */
5464/* Quad manipulation (load/store two floats at a time) */
76a66253
JM
5465
5466/* lfq */
99e300ef 5467static void gen_lfq(DisasContext *ctx)
76a66253 5468{
01a4afeb 5469 int rd = rD(ctx->opcode);
76db3ba4
AJ
5470 TCGv t0;
5471 gen_set_access_type(ctx, ACCESS_FLOAT);
5472 t0 = tcg_temp_new();
5473 gen_addr_imm_index(ctx, t0, 0);
5474 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5475 gen_addr_add(ctx, t0, t0, 8);
5476 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5477 tcg_temp_free(t0);
76a66253
JM
5478}
5479
5480/* lfqu */
99e300ef 5481static void gen_lfqu(DisasContext *ctx)
76a66253
JM
5482{
5483 int ra = rA(ctx->opcode);
01a4afeb 5484 int rd = rD(ctx->opcode);
76db3ba4
AJ
5485 TCGv t0, t1;
5486 gen_set_access_type(ctx, ACCESS_FLOAT);
5487 t0 = tcg_temp_new();
5488 t1 = tcg_temp_new();
5489 gen_addr_imm_index(ctx, t0, 0);
5490 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5491 gen_addr_add(ctx, t1, t0, 8);
5492 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
76a66253 5493 if (ra != 0)
01a4afeb
AJ
5494 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5495 tcg_temp_free(t0);
5496 tcg_temp_free(t1);
76a66253
JM
5497}
5498
5499/* lfqux */
99e300ef 5500static void gen_lfqux(DisasContext *ctx)
76a66253
JM
5501{
5502 int ra = rA(ctx->opcode);
01a4afeb 5503 int rd = rD(ctx->opcode);
76db3ba4
AJ
5504 gen_set_access_type(ctx, ACCESS_FLOAT);
5505 TCGv t0, t1;
5506 t0 = tcg_temp_new();
5507 gen_addr_reg_index(ctx, t0);
5508 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5509 t1 = tcg_temp_new();
5510 gen_addr_add(ctx, t1, t0, 8);
5511 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5512 tcg_temp_free(t1);
76a66253 5513 if (ra != 0)
01a4afeb
AJ
5514 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5515 tcg_temp_free(t0);
76a66253
JM
5516}
5517
5518/* lfqx */
99e300ef 5519static void gen_lfqx(DisasContext *ctx)
76a66253 5520{
01a4afeb 5521 int rd = rD(ctx->opcode);
76db3ba4
AJ
5522 TCGv t0;
5523 gen_set_access_type(ctx, ACCESS_FLOAT);
5524 t0 = tcg_temp_new();
5525 gen_addr_reg_index(ctx, t0);
5526 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5527 gen_addr_add(ctx, t0, t0, 8);
5528 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5529 tcg_temp_free(t0);
76a66253
JM
5530}
5531
5532/* stfq */
99e300ef 5533static void gen_stfq(DisasContext *ctx)
76a66253 5534{
01a4afeb 5535 int rd = rD(ctx->opcode);
76db3ba4
AJ
5536 TCGv t0;
5537 gen_set_access_type(ctx, ACCESS_FLOAT);
5538 t0 = tcg_temp_new();
5539 gen_addr_imm_index(ctx, t0, 0);
5540 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5541 gen_addr_add(ctx, t0, t0, 8);
5542 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5543 tcg_temp_free(t0);
76a66253
JM
5544}
5545
5546/* stfqu */
99e300ef 5547static void gen_stfqu(DisasContext *ctx)
76a66253
JM
5548{
5549 int ra = rA(ctx->opcode);
01a4afeb 5550 int rd = rD(ctx->opcode);
76db3ba4
AJ
5551 TCGv t0, t1;
5552 gen_set_access_type(ctx, ACCESS_FLOAT);
5553 t0 = tcg_temp_new();
5554 gen_addr_imm_index(ctx, t0, 0);
5555 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5556 t1 = tcg_temp_new();
5557 gen_addr_add(ctx, t1, t0, 8);
5558 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5559 tcg_temp_free(t1);
76a66253 5560 if (ra != 0)
01a4afeb
AJ
5561 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5562 tcg_temp_free(t0);
76a66253
JM
5563}
5564
5565/* stfqux */
99e300ef 5566static void gen_stfqux(DisasContext *ctx)
76a66253
JM
5567{
5568 int ra = rA(ctx->opcode);
01a4afeb 5569 int rd = rD(ctx->opcode);
76db3ba4
AJ
5570 TCGv t0, t1;
5571 gen_set_access_type(ctx, ACCESS_FLOAT);
5572 t0 = tcg_temp_new();
5573 gen_addr_reg_index(ctx, t0);
5574 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5575 t1 = tcg_temp_new();
5576 gen_addr_add(ctx, t1, t0, 8);
5577 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5578 tcg_temp_free(t1);
76a66253 5579 if (ra != 0)
01a4afeb
AJ
5580 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5581 tcg_temp_free(t0);
76a66253
JM
5582}
5583
5584/* stfqx */
99e300ef 5585static void gen_stfqx(DisasContext *ctx)
76a66253 5586{
01a4afeb 5587 int rd = rD(ctx->opcode);
76db3ba4
AJ
5588 TCGv t0;
5589 gen_set_access_type(ctx, ACCESS_FLOAT);
5590 t0 = tcg_temp_new();
5591 gen_addr_reg_index(ctx, t0);
5592 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5593 gen_addr_add(ctx, t0, t0, 8);
5594 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5595 tcg_temp_free(t0);
76a66253
JM
5596}
5597
5598/* BookE specific instructions */
99e300ef 5599
54623277 5600/* XXX: not implemented on 440 ? */
99e300ef 5601static void gen_mfapidi(DisasContext *ctx)
76a66253
JM
5602{
5603 /* XXX: TODO */
e06fcd75 5604 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5605}
5606
2662a059 5607/* XXX: not implemented on 440 ? */
99e300ef 5608static void gen_tlbiva(DisasContext *ctx)
76a66253
JM
5609{
5610#if defined(CONFIG_USER_ONLY)
e06fcd75 5611 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5612#else
74d37793 5613 TCGv t0;
76db3ba4 5614 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5615 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5616 return;
5617 }
ec72e276 5618 t0 = tcg_temp_new();
76db3ba4 5619 gen_addr_reg_index(ctx, t0);
c6c7cf05 5620 gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
74d37793 5621 tcg_temp_free(t0);
76a66253
JM
5622#endif
5623}
5624
5625/* All 405 MAC instructions are translated here */
636aa200
BS
5626static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
5627 int ra, int rb, int rt, int Rc)
76a66253 5628{
182608d4
AJ
5629 TCGv t0, t1;
5630
a7812ae4
PB
5631 t0 = tcg_temp_local_new();
5632 t1 = tcg_temp_local_new();
182608d4 5633
76a66253
JM
5634 switch (opc3 & 0x0D) {
5635 case 0x05:
5636 /* macchw - macchw. - macchwo - macchwo. */
5637 /* macchws - macchws. - macchwso - macchwso. */
5638 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5639 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5640 /* mulchw - mulchw. */
182608d4
AJ
5641 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5642 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5643 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5644 break;
5645 case 0x04:
5646 /* macchwu - macchwu. - macchwuo - macchwuo. */
5647 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5648 /* mulchwu - mulchwu. */
182608d4
AJ
5649 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5650 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5651 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5652 break;
5653 case 0x01:
5654 /* machhw - machhw. - machhwo - machhwo. */
5655 /* machhws - machhws. - machhwso - machhwso. */
5656 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5657 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5658 /* mulhhw - mulhhw. */
182608d4
AJ
5659 tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5660 tcg_gen_ext16s_tl(t0, t0);
5661 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5662 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5663 break;
5664 case 0x00:
5665 /* machhwu - machhwu. - machhwuo - machhwuo. */
5666 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5667 /* mulhhwu - mulhhwu. */
182608d4
AJ
5668 tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5669 tcg_gen_ext16u_tl(t0, t0);
5670 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5671 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5672 break;
5673 case 0x0D:
5674 /* maclhw - maclhw. - maclhwo - maclhwo. */
5675 /* maclhws - maclhws. - maclhwso - maclhwso. */
5676 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5677 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5678 /* mullhw - mullhw. */
182608d4
AJ
5679 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5680 tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
76a66253
JM
5681 break;
5682 case 0x0C:
5683 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5684 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5685 /* mullhwu - mullhwu. */
182608d4
AJ
5686 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5687 tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
76a66253
JM
5688 break;
5689 }
76a66253 5690 if (opc2 & 0x04) {
182608d4
AJ
5691 /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5692 tcg_gen_mul_tl(t1, t0, t1);
5693 if (opc2 & 0x02) {
5694 /* nmultiply-and-accumulate (0x0E) */
5695 tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5696 } else {
5697 /* multiply-and-accumulate (0x0C) */
5698 tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5699 }
5700
5701 if (opc3 & 0x12) {
5702 /* Check overflow and/or saturate */
5703 int l1 = gen_new_label();
5704
5705 if (opc3 & 0x10) {
5706 /* Start with XER OV disabled, the most likely case */
da91a00f 5707 tcg_gen_movi_tl(cpu_ov, 0);
182608d4
AJ
5708 }
5709 if (opc3 & 0x01) {
5710 /* Signed */
5711 tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5712 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5713 tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5714 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
bdc4e053 5715 if (opc3 & 0x02) {
182608d4
AJ
5716 /* Saturate */
5717 tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5718 tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5719 }
5720 } else {
5721 /* Unsigned */
5722 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
bdc4e053 5723 if (opc3 & 0x02) {
182608d4
AJ
5724 /* Saturate */
5725 tcg_gen_movi_tl(t0, UINT32_MAX);
5726 }
5727 }
5728 if (opc3 & 0x10) {
5729 /* Check overflow */
da91a00f
RH
5730 tcg_gen_movi_tl(cpu_ov, 1);
5731 tcg_gen_movi_tl(cpu_so, 1);
182608d4
AJ
5732 }
5733 gen_set_label(l1);
5734 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5735 }
5736 } else {
5737 tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
76a66253 5738 }
182608d4
AJ
5739 tcg_temp_free(t0);
5740 tcg_temp_free(t1);
76a66253
JM
5741 if (unlikely(Rc) != 0) {
5742 /* Update Rc0 */
182608d4 5743 gen_set_Rc0(ctx, cpu_gpr[rt]);
76a66253
JM
5744 }
5745}
5746
a750fc0b 5747#define GEN_MAC_HANDLER(name, opc2, opc3) \
99e300ef 5748static void glue(gen_, name)(DisasContext *ctx) \
76a66253
JM
5749{ \
5750 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5751 rD(ctx->opcode), Rc(ctx->opcode)); \
5752}
5753
5754/* macchw - macchw. */
a750fc0b 5755GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
76a66253 5756/* macchwo - macchwo. */
a750fc0b 5757GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
76a66253 5758/* macchws - macchws. */
a750fc0b 5759GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
76a66253 5760/* macchwso - macchwso. */
a750fc0b 5761GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
76a66253 5762/* macchwsu - macchwsu. */
a750fc0b 5763GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
76a66253 5764/* macchwsuo - macchwsuo. */
a750fc0b 5765GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
76a66253 5766/* macchwu - macchwu. */
a750fc0b 5767GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
76a66253 5768/* macchwuo - macchwuo. */
a750fc0b 5769GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
76a66253 5770/* machhw - machhw. */
a750fc0b 5771GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
76a66253 5772/* machhwo - machhwo. */
a750fc0b 5773GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
76a66253 5774/* machhws - machhws. */
a750fc0b 5775GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
76a66253 5776/* machhwso - machhwso. */
a750fc0b 5777GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
76a66253 5778/* machhwsu - machhwsu. */
a750fc0b 5779GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
76a66253 5780/* machhwsuo - machhwsuo. */
a750fc0b 5781GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
76a66253 5782/* machhwu - machhwu. */
a750fc0b 5783GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
76a66253 5784/* machhwuo - machhwuo. */
a750fc0b 5785GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
76a66253 5786/* maclhw - maclhw. */
a750fc0b 5787GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
76a66253 5788/* maclhwo - maclhwo. */
a750fc0b 5789GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
76a66253 5790/* maclhws - maclhws. */
a750fc0b 5791GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
76a66253 5792/* maclhwso - maclhwso. */
a750fc0b 5793GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
76a66253 5794/* maclhwu - maclhwu. */
a750fc0b 5795GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
76a66253 5796/* maclhwuo - maclhwuo. */
a750fc0b 5797GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
76a66253 5798/* maclhwsu - maclhwsu. */
a750fc0b 5799GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
76a66253 5800/* maclhwsuo - maclhwsuo. */
a750fc0b 5801GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
76a66253 5802/* nmacchw - nmacchw. */
a750fc0b 5803GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
76a66253 5804/* nmacchwo - nmacchwo. */
a750fc0b 5805GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
76a66253 5806/* nmacchws - nmacchws. */
a750fc0b 5807GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
76a66253 5808/* nmacchwso - nmacchwso. */
a750fc0b 5809GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
76a66253 5810/* nmachhw - nmachhw. */
a750fc0b 5811GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
76a66253 5812/* nmachhwo - nmachhwo. */
a750fc0b 5813GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
76a66253 5814/* nmachhws - nmachhws. */
a750fc0b 5815GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
76a66253 5816/* nmachhwso - nmachhwso. */
a750fc0b 5817GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
76a66253 5818/* nmaclhw - nmaclhw. */
a750fc0b 5819GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
76a66253 5820/* nmaclhwo - nmaclhwo. */
a750fc0b 5821GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
76a66253 5822/* nmaclhws - nmaclhws. */
a750fc0b 5823GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
76a66253 5824/* nmaclhwso - nmaclhwso. */
a750fc0b 5825GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
76a66253
JM
5826
5827/* mulchw - mulchw. */
a750fc0b 5828GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
76a66253 5829/* mulchwu - mulchwu. */
a750fc0b 5830GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
76a66253 5831/* mulhhw - mulhhw. */
a750fc0b 5832GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
76a66253 5833/* mulhhwu - mulhhwu. */
a750fc0b 5834GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
76a66253 5835/* mullhw - mullhw. */
a750fc0b 5836GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
76a66253 5837/* mullhwu - mullhwu. */
a750fc0b 5838GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
76a66253
JM
5839
5840/* mfdcr */
99e300ef 5841static void gen_mfdcr(DisasContext *ctx)
76a66253
JM
5842{
5843#if defined(CONFIG_USER_ONLY)
e06fcd75 5844 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253 5845#else
06dca6a7 5846 TCGv dcrn;
76db3ba4 5847 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5848 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253
JM
5849 return;
5850 }
06dca6a7
AJ
5851 /* NIP cannot be restored if the memory exception comes from an helper */
5852 gen_update_nip(ctx, ctx->nip - 4);
5853 dcrn = tcg_const_tl(SPR(ctx->opcode));
d0f1562d 5854 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
06dca6a7 5855 tcg_temp_free(dcrn);
76a66253
JM
5856#endif
5857}
5858
5859/* mtdcr */
99e300ef 5860static void gen_mtdcr(DisasContext *ctx)
76a66253
JM
5861{
5862#if defined(CONFIG_USER_ONLY)
e06fcd75 5863 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253 5864#else
06dca6a7 5865 TCGv dcrn;
76db3ba4 5866 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5867 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253
JM
5868 return;
5869 }
06dca6a7
AJ
5870 /* NIP cannot be restored if the memory exception comes from an helper */
5871 gen_update_nip(ctx, ctx->nip - 4);
5872 dcrn = tcg_const_tl(SPR(ctx->opcode));
d0f1562d 5873 gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
06dca6a7 5874 tcg_temp_free(dcrn);
a42bd6cc
JM
5875#endif
5876}
5877
5878/* mfdcrx */
2662a059 5879/* XXX: not implemented on 440 ? */
99e300ef 5880static void gen_mfdcrx(DisasContext *ctx)
a42bd6cc
JM
5881{
5882#if defined(CONFIG_USER_ONLY)
e06fcd75 5883 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
a42bd6cc 5884#else
76db3ba4 5885 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5886 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
a42bd6cc
JM
5887 return;
5888 }
06dca6a7
AJ
5889 /* NIP cannot be restored if the memory exception comes from an helper */
5890 gen_update_nip(ctx, ctx->nip - 4);
d0f1562d
BS
5891 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
5892 cpu_gpr[rA(ctx->opcode)]);
a750fc0b 5893 /* Note: Rc update flag set leads to undefined state of Rc0 */
a42bd6cc
JM
5894#endif
5895}
5896
5897/* mtdcrx */
2662a059 5898/* XXX: not implemented on 440 ? */
99e300ef 5899static void gen_mtdcrx(DisasContext *ctx)
a42bd6cc
JM
5900{
5901#if defined(CONFIG_USER_ONLY)
e06fcd75 5902 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
a42bd6cc 5903#else
76db3ba4 5904 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5905 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
a42bd6cc
JM
5906 return;
5907 }
06dca6a7
AJ
5908 /* NIP cannot be restored if the memory exception comes from an helper */
5909 gen_update_nip(ctx, ctx->nip - 4);
d0f1562d
BS
5910 gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
5911 cpu_gpr[rS(ctx->opcode)]);
a750fc0b 5912 /* Note: Rc update flag set leads to undefined state of Rc0 */
76a66253
JM
5913#endif
5914}
5915
a750fc0b 5916/* mfdcrux (PPC 460) : user-mode access to DCR */
99e300ef 5917static void gen_mfdcrux(DisasContext *ctx)
a750fc0b 5918{
06dca6a7
AJ
5919 /* NIP cannot be restored if the memory exception comes from an helper */
5920 gen_update_nip(ctx, ctx->nip - 4);
d0f1562d
BS
5921 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
5922 cpu_gpr[rA(ctx->opcode)]);
a750fc0b
JM
5923 /* Note: Rc update flag set leads to undefined state of Rc0 */
5924}
5925
5926/* mtdcrux (PPC 460) : user-mode access to DCR */
99e300ef 5927static void gen_mtdcrux(DisasContext *ctx)
a750fc0b 5928{
06dca6a7
AJ
5929 /* NIP cannot be restored if the memory exception comes from an helper */
5930 gen_update_nip(ctx, ctx->nip - 4);
975e5463 5931 gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
d0f1562d 5932 cpu_gpr[rS(ctx->opcode)]);
a750fc0b
JM
5933 /* Note: Rc update flag set leads to undefined state of Rc0 */
5934}
5935
76a66253 5936/* dccci */
99e300ef 5937static void gen_dccci(DisasContext *ctx)
76a66253
JM
5938{
5939#if defined(CONFIG_USER_ONLY)
e06fcd75 5940 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5941#else
76db3ba4 5942 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5943 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5944 return;
5945 }
5946 /* interpreted as no-op */
5947#endif
5948}
5949
5950/* dcread */
99e300ef 5951static void gen_dcread(DisasContext *ctx)
76a66253
JM
5952{
5953#if defined(CONFIG_USER_ONLY)
e06fcd75 5954 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5955#else
b61f2753 5956 TCGv EA, val;
76db3ba4 5957 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5958 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5959 return;
5960 }
76db3ba4 5961 gen_set_access_type(ctx, ACCESS_CACHE);
a7812ae4 5962 EA = tcg_temp_new();
76db3ba4 5963 gen_addr_reg_index(ctx, EA);
a7812ae4 5964 val = tcg_temp_new();
76db3ba4 5965 gen_qemu_ld32u(ctx, val, EA);
b61f2753
AJ
5966 tcg_temp_free(val);
5967 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5968 tcg_temp_free(EA);
76a66253
JM
5969#endif
5970}
5971
5972/* icbt */
e8eaa2c0 5973static void gen_icbt_40x(DisasContext *ctx)
76a66253
JM
5974{
5975 /* interpreted as no-op */
5976 /* XXX: specification say this is treated as a load by the MMU
5977 * but does not generate any exception
5978 */
5979}
5980
5981/* iccci */
99e300ef 5982static void gen_iccci(DisasContext *ctx)
76a66253
JM
5983{
5984#if defined(CONFIG_USER_ONLY)
e06fcd75 5985 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5986#else
76db3ba4 5987 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5988 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5989 return;
5990 }
5991 /* interpreted as no-op */
5992#endif
5993}
5994
5995/* icread */
99e300ef 5996static void gen_icread(DisasContext *ctx)
76a66253
JM
5997{
5998#if defined(CONFIG_USER_ONLY)
e06fcd75 5999 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 6000#else
76db3ba4 6001 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6002 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
6003 return;
6004 }
6005 /* interpreted as no-op */
6006#endif
6007}
6008
76db3ba4 6009/* rfci (mem_idx only) */
e8eaa2c0 6010static void gen_rfci_40x(DisasContext *ctx)
a42bd6cc
JM
6011{
6012#if defined(CONFIG_USER_ONLY)
e06fcd75 6013 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc 6014#else
76db3ba4 6015 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6016 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc
JM
6017 return;
6018 }
6019 /* Restore CPU state */
e5f17ac6 6020 gen_helper_40x_rfci(cpu_env);
e06fcd75 6021 gen_sync_exception(ctx);
a42bd6cc
JM
6022#endif
6023}
6024
99e300ef 6025static void gen_rfci(DisasContext *ctx)
a42bd6cc
JM
6026{
6027#if defined(CONFIG_USER_ONLY)
e06fcd75 6028 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc 6029#else
76db3ba4 6030 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6031 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc
JM
6032 return;
6033 }
6034 /* Restore CPU state */
e5f17ac6 6035 gen_helper_rfci(cpu_env);
e06fcd75 6036 gen_sync_exception(ctx);
a42bd6cc
JM
6037#endif
6038}
6039
6040/* BookE specific */
99e300ef 6041
54623277 6042/* XXX: not implemented on 440 ? */
99e300ef 6043static void gen_rfdi(DisasContext *ctx)
76a66253
JM
6044{
6045#if defined(CONFIG_USER_ONLY)
e06fcd75 6046 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 6047#else
76db3ba4 6048 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6049 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
6050 return;
6051 }
6052 /* Restore CPU state */
e5f17ac6 6053 gen_helper_rfdi(cpu_env);
e06fcd75 6054 gen_sync_exception(ctx);
76a66253
JM
6055#endif
6056}
6057
2662a059 6058/* XXX: not implemented on 440 ? */
99e300ef 6059static void gen_rfmci(DisasContext *ctx)
a42bd6cc
JM
6060{
6061#if defined(CONFIG_USER_ONLY)
e06fcd75 6062 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc 6063#else
76db3ba4 6064 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6065 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc
JM
6066 return;
6067 }
6068 /* Restore CPU state */
e5f17ac6 6069 gen_helper_rfmci(cpu_env);
e06fcd75 6070 gen_sync_exception(ctx);
a42bd6cc
JM
6071#endif
6072}
5eb7995e 6073
d9bce9d9 6074/* TLB management - PowerPC 405 implementation */
e8eaa2c0 6075
54623277 6076/* tlbre */
e8eaa2c0 6077static void gen_tlbre_40x(DisasContext *ctx)
76a66253
JM
6078{
6079#if defined(CONFIG_USER_ONLY)
e06fcd75 6080 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 6081#else
76db3ba4 6082 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6083 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
6084 return;
6085 }
6086 switch (rB(ctx->opcode)) {
6087 case 0:
c6c7cf05
BS
6088 gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
6089 cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
6090 break;
6091 case 1:
c6c7cf05
BS
6092 gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
6093 cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
6094 break;
6095 default:
e06fcd75 6096 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253 6097 break;
9a64fbe4 6098 }
76a66253
JM
6099#endif
6100}
6101
d9bce9d9 6102/* tlbsx - tlbsx. */
e8eaa2c0 6103static void gen_tlbsx_40x(DisasContext *ctx)
76a66253
JM
6104{
6105#if defined(CONFIG_USER_ONLY)
e06fcd75 6106 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 6107#else
74d37793 6108 TCGv t0;
76db3ba4 6109 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6110 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
6111 return;
6112 }
74d37793 6113 t0 = tcg_temp_new();
76db3ba4 6114 gen_addr_reg_index(ctx, t0);
c6c7cf05 6115 gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793
AJ
6116 tcg_temp_free(t0);
6117 if (Rc(ctx->opcode)) {
6118 int l1 = gen_new_label();
da91a00f 6119 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
74d37793
AJ
6120 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6121 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6122 gen_set_label(l1);
6123 }
76a66253 6124#endif
79aceca5
FB
6125}
6126
76a66253 6127/* tlbwe */
e8eaa2c0 6128static void gen_tlbwe_40x(DisasContext *ctx)
79aceca5 6129{
76a66253 6130#if defined(CONFIG_USER_ONLY)
e06fcd75 6131 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 6132#else
76db3ba4 6133 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6134 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
6135 return;
6136 }
6137 switch (rB(ctx->opcode)) {
6138 case 0:
c6c7cf05
BS
6139 gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
6140 cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
6141 break;
6142 case 1:
c6c7cf05
BS
6143 gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
6144 cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
6145 break;
6146 default:
e06fcd75 6147 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253 6148 break;
9a64fbe4 6149 }
76a66253
JM
6150#endif
6151}
6152
a4bb6c3e 6153/* TLB management - PowerPC 440 implementation */
e8eaa2c0 6154
54623277 6155/* tlbre */
e8eaa2c0 6156static void gen_tlbre_440(DisasContext *ctx)
5eb7995e
JM
6157{
6158#if defined(CONFIG_USER_ONLY)
e06fcd75 6159 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e 6160#else
76db3ba4 6161 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6162 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e
JM
6163 return;
6164 }
6165 switch (rB(ctx->opcode)) {
6166 case 0:
5eb7995e 6167 case 1:
5eb7995e 6168 case 2:
74d37793
AJ
6169 {
6170 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
c6c7cf05
BS
6171 gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
6172 t0, cpu_gpr[rA(ctx->opcode)]);
74d37793
AJ
6173 tcg_temp_free_i32(t0);
6174 }
5eb7995e
JM
6175 break;
6176 default:
e06fcd75 6177 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5eb7995e
JM
6178 break;
6179 }
6180#endif
6181}
6182
6183/* tlbsx - tlbsx. */
e8eaa2c0 6184static void gen_tlbsx_440(DisasContext *ctx)
5eb7995e
JM
6185{
6186#if defined(CONFIG_USER_ONLY)
e06fcd75 6187 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e 6188#else
74d37793 6189 TCGv t0;
76db3ba4 6190 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6191 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e
JM
6192 return;
6193 }
74d37793 6194 t0 = tcg_temp_new();
76db3ba4 6195 gen_addr_reg_index(ctx, t0);
c6c7cf05 6196 gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793
AJ
6197 tcg_temp_free(t0);
6198 if (Rc(ctx->opcode)) {
6199 int l1 = gen_new_label();
da91a00f 6200 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
74d37793
AJ
6201 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6202 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6203 gen_set_label(l1);
6204 }
5eb7995e
JM
6205#endif
6206}
6207
6208/* tlbwe */
e8eaa2c0 6209static void gen_tlbwe_440(DisasContext *ctx)
5eb7995e
JM
6210{
6211#if defined(CONFIG_USER_ONLY)
e06fcd75 6212 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e 6213#else
76db3ba4 6214 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6215 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e
JM
6216 return;
6217 }
6218 switch (rB(ctx->opcode)) {
6219 case 0:
5eb7995e 6220 case 1:
5eb7995e 6221 case 2:
74d37793
AJ
6222 {
6223 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
c6c7cf05
BS
6224 gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
6225 cpu_gpr[rS(ctx->opcode)]);
74d37793
AJ
6226 tcg_temp_free_i32(t0);
6227 }
5eb7995e
JM
6228 break;
6229 default:
e06fcd75 6230 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5eb7995e
JM
6231 break;
6232 }
6233#endif
6234}
6235
01662f3e
AG
6236/* TLB management - PowerPC BookE 2.06 implementation */
6237
6238/* tlbre */
6239static void gen_tlbre_booke206(DisasContext *ctx)
6240{
6241#if defined(CONFIG_USER_ONLY)
6242 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6243#else
6244 if (unlikely(!ctx->mem_idx)) {
6245 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6246 return;
6247 }
6248
c6c7cf05 6249 gen_helper_booke206_tlbre(cpu_env);
01662f3e
AG
6250#endif
6251}
6252
6253/* tlbsx - tlbsx. */
6254static void gen_tlbsx_booke206(DisasContext *ctx)
6255{
6256#if defined(CONFIG_USER_ONLY)
6257 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6258#else
6259 TCGv t0;
6260 if (unlikely(!ctx->mem_idx)) {
6261 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6262 return;
6263 }
6264
6265 if (rA(ctx->opcode)) {
6266 t0 = tcg_temp_new();
6267 tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
6268 } else {
6269 t0 = tcg_const_tl(0);
6270 }
6271
6272 tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
c6c7cf05 6273 gen_helper_booke206_tlbsx(cpu_env, t0);
01662f3e
AG
6274#endif
6275}
6276
6277/* tlbwe */
6278static void gen_tlbwe_booke206(DisasContext *ctx)
6279{
6280#if defined(CONFIG_USER_ONLY)
6281 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6282#else
6283 if (unlikely(!ctx->mem_idx)) {
6284 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6285 return;
6286 }
3f162d11 6287 gen_update_nip(ctx, ctx->nip - 4);
c6c7cf05 6288 gen_helper_booke206_tlbwe(cpu_env);
01662f3e
AG
6289#endif
6290}
6291
6292static void gen_tlbivax_booke206(DisasContext *ctx)
6293{
6294#if defined(CONFIG_USER_ONLY)
6295 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6296#else
6297 TCGv t0;
6298 if (unlikely(!ctx->mem_idx)) {
6299 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6300 return;
6301 }
6302
6303 t0 = tcg_temp_new();
6304 gen_addr_reg_index(ctx, t0);
6305
c6c7cf05 6306 gen_helper_booke206_tlbivax(cpu_env, t0);
01662f3e
AG
6307#endif
6308}
6309
6d3db821
AG
6310static void gen_tlbilx_booke206(DisasContext *ctx)
6311{
6312#if defined(CONFIG_USER_ONLY)
6313 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6314#else
6315 TCGv t0;
6316 if (unlikely(!ctx->mem_idx)) {
6317 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6318 return;
6319 }
6320
6321 t0 = tcg_temp_new();
6322 gen_addr_reg_index(ctx, t0);
6323
6324 switch((ctx->opcode >> 21) & 0x3) {
6325 case 0:
c6c7cf05 6326 gen_helper_booke206_tlbilx0(cpu_env, t0);
6d3db821
AG
6327 break;
6328 case 1:
c6c7cf05 6329 gen_helper_booke206_tlbilx1(cpu_env, t0);
6d3db821
AG
6330 break;
6331 case 3:
c6c7cf05 6332 gen_helper_booke206_tlbilx3(cpu_env, t0);
6d3db821
AG
6333 break;
6334 default:
6335 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6336 break;
6337 }
6338
6339 tcg_temp_free(t0);
6340#endif
6341}
6342
01662f3e 6343
76a66253 6344/* wrtee */
99e300ef 6345static void gen_wrtee(DisasContext *ctx)
76a66253
JM
6346{
6347#if defined(CONFIG_USER_ONLY)
e06fcd75 6348 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 6349#else
6527f6ea 6350 TCGv t0;
76db3ba4 6351 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6352 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
6353 return;
6354 }
6527f6ea
AJ
6355 t0 = tcg_temp_new();
6356 tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6357 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6358 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6359 tcg_temp_free(t0);
dee96f6c
JM
6360 /* Stop translation to have a chance to raise an exception
6361 * if we just set msr_ee to 1
6362 */
e06fcd75 6363 gen_stop_exception(ctx);
76a66253
JM
6364#endif
6365}
6366
6367/* wrteei */
99e300ef 6368static void gen_wrteei(DisasContext *ctx)
76a66253
JM
6369{
6370#if defined(CONFIG_USER_ONLY)
e06fcd75 6371 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 6372#else
76db3ba4 6373 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6374 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
6375 return;
6376 }
fbe73008 6377 if (ctx->opcode & 0x00008000) {
6527f6ea
AJ
6378 tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6379 /* Stop translation to have a chance to raise an exception */
e06fcd75 6380 gen_stop_exception(ctx);
6527f6ea 6381 } else {
1b6e5f99 6382 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6527f6ea 6383 }
76a66253
JM
6384#endif
6385}
6386
08e46e54 6387/* PowerPC 440 specific instructions */
99e300ef 6388
54623277 6389/* dlmzb */
99e300ef 6390static void gen_dlmzb(DisasContext *ctx)
76a66253 6391{
ef0d51af 6392 TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
d15f74fb
BS
6393 gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
6394 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
ef0d51af 6395 tcg_temp_free_i32(t0);
76a66253
JM
6396}
6397
6398/* mbar replaces eieio on 440 */
99e300ef 6399static void gen_mbar(DisasContext *ctx)
76a66253
JM
6400{
6401 /* interpreted as no-op */
6402}
6403
6404/* msync replaces sync on 440 */
dcb2b9e1 6405static void gen_msync_4xx(DisasContext *ctx)
76a66253
JM
6406{
6407 /* interpreted as no-op */
6408}
6409
6410/* icbt */
e8eaa2c0 6411static void gen_icbt_440(DisasContext *ctx)
76a66253
JM
6412{
6413 /* interpreted as no-op */
6414 /* XXX: specification say this is treated as a load by the MMU
6415 * but does not generate any exception
6416 */
79aceca5
FB
6417}
6418
9e0b5cb1
AG
6419/* Embedded.Processor Control */
6420
6421static void gen_msgclr(DisasContext *ctx)
6422{
6423#if defined(CONFIG_USER_ONLY)
6424 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6425#else
6426 if (unlikely(ctx->mem_idx == 0)) {
6427 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6428 return;
6429 }
6430
e5f17ac6 6431 gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9e0b5cb1
AG
6432#endif
6433}
6434
d5d11a39
AG
6435static void gen_msgsnd(DisasContext *ctx)
6436{
6437#if defined(CONFIG_USER_ONLY)
6438 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6439#else
6440 if (unlikely(ctx->mem_idx == 0)) {
6441 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6442 return;
6443 }
6444
6445 gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
6446#endif
6447}
6448
a9d9eb8f
JM
6449/*** Altivec vector extension ***/
6450/* Altivec registers moves */
a9d9eb8f 6451
636aa200 6452static inline TCGv_ptr gen_avr_ptr(int reg)
564e571a 6453{
e4704b3b 6454 TCGv_ptr r = tcg_temp_new_ptr();
564e571a
AJ
6455 tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
6456 return r;
6457}
6458
a9d9eb8f 6459#define GEN_VR_LDX(name, opc2, opc3) \
99e300ef 6460static void glue(gen_, name)(DisasContext *ctx) \
a9d9eb8f 6461{ \
fe1e5c53 6462 TCGv EA; \
a9d9eb8f 6463 if (unlikely(!ctx->altivec_enabled)) { \
e06fcd75 6464 gen_exception(ctx, POWERPC_EXCP_VPU); \
a9d9eb8f
JM
6465 return; \
6466 } \
76db3ba4 6467 gen_set_access_type(ctx, ACCESS_INT); \
fe1e5c53 6468 EA = tcg_temp_new(); \
76db3ba4 6469 gen_addr_reg_index(ctx, EA); \
fe1e5c53 6470 tcg_gen_andi_tl(EA, EA, ~0xf); \
76db3ba4
AJ
6471 if (ctx->le_mode) { \
6472 gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53 6473 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6474 gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6475 } else { \
76db3ba4 6476 gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6477 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6478 gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53
AJ
6479 } \
6480 tcg_temp_free(EA); \
a9d9eb8f
JM
6481}
6482
6483#define GEN_VR_STX(name, opc2, opc3) \
99e300ef 6484static void gen_st##name(DisasContext *ctx) \
a9d9eb8f 6485{ \
fe1e5c53 6486 TCGv EA; \
a9d9eb8f 6487 if (unlikely(!ctx->altivec_enabled)) { \
e06fcd75 6488 gen_exception(ctx, POWERPC_EXCP_VPU); \
a9d9eb8f
JM
6489 return; \
6490 } \
76db3ba4 6491 gen_set_access_type(ctx, ACCESS_INT); \
fe1e5c53 6492 EA = tcg_temp_new(); \
76db3ba4 6493 gen_addr_reg_index(ctx, EA); \
fe1e5c53 6494 tcg_gen_andi_tl(EA, EA, ~0xf); \
76db3ba4
AJ
6495 if (ctx->le_mode) { \
6496 gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53 6497 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6498 gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6499 } else { \
76db3ba4 6500 gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6501 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6502 gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53
AJ
6503 } \
6504 tcg_temp_free(EA); \
a9d9eb8f
JM
6505}
6506
cbfb6ae9 6507#define GEN_VR_LVE(name, opc2, opc3) \
99e300ef 6508static void gen_lve##name(DisasContext *ctx) \
cbfb6ae9
AJ
6509 { \
6510 TCGv EA; \
6511 TCGv_ptr rs; \
6512 if (unlikely(!ctx->altivec_enabled)) { \
6513 gen_exception(ctx, POWERPC_EXCP_VPU); \
6514 return; \
6515 } \
6516 gen_set_access_type(ctx, ACCESS_INT); \
6517 EA = tcg_temp_new(); \
6518 gen_addr_reg_index(ctx, EA); \
6519 rs = gen_avr_ptr(rS(ctx->opcode)); \
2f5a189c 6520 gen_helper_lve##name(cpu_env, rs, EA); \
cbfb6ae9
AJ
6521 tcg_temp_free(EA); \
6522 tcg_temp_free_ptr(rs); \
6523 }
6524
6525#define GEN_VR_STVE(name, opc2, opc3) \
99e300ef 6526static void gen_stve##name(DisasContext *ctx) \
cbfb6ae9
AJ
6527 { \
6528 TCGv EA; \
6529 TCGv_ptr rs; \
6530 if (unlikely(!ctx->altivec_enabled)) { \
6531 gen_exception(ctx, POWERPC_EXCP_VPU); \
6532 return; \
6533 } \
6534 gen_set_access_type(ctx, ACCESS_INT); \
6535 EA = tcg_temp_new(); \
6536 gen_addr_reg_index(ctx, EA); \
6537 rs = gen_avr_ptr(rS(ctx->opcode)); \
2f5a189c 6538 gen_helper_stve##name(cpu_env, rs, EA); \
cbfb6ae9
AJ
6539 tcg_temp_free(EA); \
6540 tcg_temp_free_ptr(rs); \
6541 }
6542
fe1e5c53 6543GEN_VR_LDX(lvx, 0x07, 0x03);
a9d9eb8f 6544/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
fe1e5c53 6545GEN_VR_LDX(lvxl, 0x07, 0x0B);
a9d9eb8f 6546
cbfb6ae9
AJ
6547GEN_VR_LVE(bx, 0x07, 0x00);
6548GEN_VR_LVE(hx, 0x07, 0x01);
6549GEN_VR_LVE(wx, 0x07, 0x02);
6550
fe1e5c53 6551GEN_VR_STX(svx, 0x07, 0x07);
a9d9eb8f 6552/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
fe1e5c53 6553GEN_VR_STX(svxl, 0x07, 0x0F);
a9d9eb8f 6554
cbfb6ae9
AJ
6555GEN_VR_STVE(bx, 0x07, 0x04);
6556GEN_VR_STVE(hx, 0x07, 0x05);
6557GEN_VR_STVE(wx, 0x07, 0x06);
6558
99e300ef 6559static void gen_lvsl(DisasContext *ctx)
bf8d8ded
AJ
6560{
6561 TCGv_ptr rd;
6562 TCGv EA;
6563 if (unlikely(!ctx->altivec_enabled)) {
6564 gen_exception(ctx, POWERPC_EXCP_VPU);
6565 return;
6566 }
6567 EA = tcg_temp_new();
6568 gen_addr_reg_index(ctx, EA);
6569 rd = gen_avr_ptr(rD(ctx->opcode));
6570 gen_helper_lvsl(rd, EA);
6571 tcg_temp_free(EA);
6572 tcg_temp_free_ptr(rd);
6573}
6574
99e300ef 6575static void gen_lvsr(DisasContext *ctx)
bf8d8ded
AJ
6576{
6577 TCGv_ptr rd;
6578 TCGv EA;
6579 if (unlikely(!ctx->altivec_enabled)) {
6580 gen_exception(ctx, POWERPC_EXCP_VPU);
6581 return;
6582 }
6583 EA = tcg_temp_new();
6584 gen_addr_reg_index(ctx, EA);
6585 rd = gen_avr_ptr(rD(ctx->opcode));
6586 gen_helper_lvsr(rd, EA);
6587 tcg_temp_free(EA);
6588 tcg_temp_free_ptr(rd);
6589}
6590
99e300ef 6591static void gen_mfvscr(DisasContext *ctx)
785f451b
AJ
6592{
6593 TCGv_i32 t;
6594 if (unlikely(!ctx->altivec_enabled)) {
6595 gen_exception(ctx, POWERPC_EXCP_VPU);
6596 return;
6597 }
6598 tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
6599 t = tcg_temp_new_i32();
1328c2bf 6600 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
785f451b 6601 tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
fce5ecb7 6602 tcg_temp_free_i32(t);
785f451b
AJ
6603}
6604
99e300ef 6605static void gen_mtvscr(DisasContext *ctx)
785f451b 6606{
6e87b7c7 6607 TCGv_ptr p;
785f451b
AJ
6608 if (unlikely(!ctx->altivec_enabled)) {
6609 gen_exception(ctx, POWERPC_EXCP_VPU);
6610 return;
6611 }
6e87b7c7 6612 p = gen_avr_ptr(rD(ctx->opcode));
d15f74fb 6613 gen_helper_mtvscr(cpu_env, p);
6e87b7c7 6614 tcg_temp_free_ptr(p);
785f451b
AJ
6615}
6616
7a9b96cf
AJ
6617/* Logical operations */
6618#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
99e300ef 6619static void glue(gen_, name)(DisasContext *ctx) \
7a9b96cf
AJ
6620{ \
6621 if (unlikely(!ctx->altivec_enabled)) { \
6622 gen_exception(ctx, POWERPC_EXCP_VPU); \
6623 return; \
6624 } \
6625 tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
6626 tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
6627}
6628
6629GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
6630GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
6631GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
6632GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
6633GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
6634
8e27dd6f 6635#define GEN_VXFORM(name, opc2, opc3) \
99e300ef 6636static void glue(gen_, name)(DisasContext *ctx) \
8e27dd6f
AJ
6637{ \
6638 TCGv_ptr ra, rb, rd; \
6639 if (unlikely(!ctx->altivec_enabled)) { \
6640 gen_exception(ctx, POWERPC_EXCP_VPU); \
6641 return; \
6642 } \
6643 ra = gen_avr_ptr(rA(ctx->opcode)); \
6644 rb = gen_avr_ptr(rB(ctx->opcode)); \
6645 rd = gen_avr_ptr(rD(ctx->opcode)); \
6646 gen_helper_##name (rd, ra, rb); \
6647 tcg_temp_free_ptr(ra); \
6648 tcg_temp_free_ptr(rb); \
6649 tcg_temp_free_ptr(rd); \
6650}
6651
d15f74fb
BS
6652#define GEN_VXFORM_ENV(name, opc2, opc3) \
6653static void glue(gen_, name)(DisasContext *ctx) \
6654{ \
6655 TCGv_ptr ra, rb, rd; \
6656 if (unlikely(!ctx->altivec_enabled)) { \
6657 gen_exception(ctx, POWERPC_EXCP_VPU); \
6658 return; \
6659 } \
6660 ra = gen_avr_ptr(rA(ctx->opcode)); \
6661 rb = gen_avr_ptr(rB(ctx->opcode)); \
6662 rd = gen_avr_ptr(rD(ctx->opcode)); \
54cddd21 6663 gen_helper_##name(cpu_env, rd, ra, rb); \
d15f74fb
BS
6664 tcg_temp_free_ptr(ra); \
6665 tcg_temp_free_ptr(rb); \
6666 tcg_temp_free_ptr(rd); \
6667}
6668
7872c51c
AJ
6669GEN_VXFORM(vaddubm, 0, 0);
6670GEN_VXFORM(vadduhm, 0, 1);
6671GEN_VXFORM(vadduwm, 0, 2);
6672GEN_VXFORM(vsububm, 0, 16);
6673GEN_VXFORM(vsubuhm, 0, 17);
6674GEN_VXFORM(vsubuwm, 0, 18);
e4039339
AJ
6675GEN_VXFORM(vmaxub, 1, 0);
6676GEN_VXFORM(vmaxuh, 1, 1);
6677GEN_VXFORM(vmaxuw, 1, 2);
6678GEN_VXFORM(vmaxsb, 1, 4);
6679GEN_VXFORM(vmaxsh, 1, 5);
6680GEN_VXFORM(vmaxsw, 1, 6);
6681GEN_VXFORM(vminub, 1, 8);
6682GEN_VXFORM(vminuh, 1, 9);
6683GEN_VXFORM(vminuw, 1, 10);
6684GEN_VXFORM(vminsb, 1, 12);
6685GEN_VXFORM(vminsh, 1, 13);
6686GEN_VXFORM(vminsw, 1, 14);
fab3cbe9
AJ
6687GEN_VXFORM(vavgub, 1, 16);
6688GEN_VXFORM(vavguh, 1, 17);
6689GEN_VXFORM(vavguw, 1, 18);
6690GEN_VXFORM(vavgsb, 1, 20);
6691GEN_VXFORM(vavgsh, 1, 21);
6692GEN_VXFORM(vavgsw, 1, 22);
3b430048
AJ
6693GEN_VXFORM(vmrghb, 6, 0);
6694GEN_VXFORM(vmrghh, 6, 1);
6695GEN_VXFORM(vmrghw, 6, 2);
6696GEN_VXFORM(vmrglb, 6, 4);
6697GEN_VXFORM(vmrglh, 6, 5);
6698GEN_VXFORM(vmrglw, 6, 6);
2c277908
AJ
6699GEN_VXFORM(vmuloub, 4, 0);
6700GEN_VXFORM(vmulouh, 4, 1);
6701GEN_VXFORM(vmulosb, 4, 4);
6702GEN_VXFORM(vmulosh, 4, 5);
6703GEN_VXFORM(vmuleub, 4, 8);
6704GEN_VXFORM(vmuleuh, 4, 9);
6705GEN_VXFORM(vmulesb, 4, 12);
6706GEN_VXFORM(vmulesh, 4, 13);
d79f0809
AJ
6707GEN_VXFORM(vslb, 2, 4);
6708GEN_VXFORM(vslh, 2, 5);
6709GEN_VXFORM(vslw, 2, 6);
07ef34c3
AJ
6710GEN_VXFORM(vsrb, 2, 8);
6711GEN_VXFORM(vsrh, 2, 9);
6712GEN_VXFORM(vsrw, 2, 10);
6713GEN_VXFORM(vsrab, 2, 12);
6714GEN_VXFORM(vsrah, 2, 13);
6715GEN_VXFORM(vsraw, 2, 14);
7b239bec
AJ
6716GEN_VXFORM(vslo, 6, 16);
6717GEN_VXFORM(vsro, 6, 17);
e343da72
AJ
6718GEN_VXFORM(vaddcuw, 0, 6);
6719GEN_VXFORM(vsubcuw, 0, 22);
d15f74fb
BS
6720GEN_VXFORM_ENV(vaddubs, 0, 8);
6721GEN_VXFORM_ENV(vadduhs, 0, 9);
6722GEN_VXFORM_ENV(vadduws, 0, 10);
6723GEN_VXFORM_ENV(vaddsbs, 0, 12);
6724GEN_VXFORM_ENV(vaddshs, 0, 13);
6725GEN_VXFORM_ENV(vaddsws, 0, 14);
6726GEN_VXFORM_ENV(vsububs, 0, 24);
6727GEN_VXFORM_ENV(vsubuhs, 0, 25);
6728GEN_VXFORM_ENV(vsubuws, 0, 26);
6729GEN_VXFORM_ENV(vsubsbs, 0, 28);
6730GEN_VXFORM_ENV(vsubshs, 0, 29);
6731GEN_VXFORM_ENV(vsubsws, 0, 30);
5e1d0985
AJ
6732GEN_VXFORM(vrlb, 2, 0);
6733GEN_VXFORM(vrlh, 2, 1);
6734GEN_VXFORM(vrlw, 2, 2);
d9430add
AJ
6735GEN_VXFORM(vsl, 2, 7);
6736GEN_VXFORM(vsr, 2, 11);
d15f74fb
BS
6737GEN_VXFORM_ENV(vpkuhum, 7, 0);
6738GEN_VXFORM_ENV(vpkuwum, 7, 1);
6739GEN_VXFORM_ENV(vpkuhus, 7, 2);
6740GEN_VXFORM_ENV(vpkuwus, 7, 3);
6741GEN_VXFORM_ENV(vpkshus, 7, 4);
6742GEN_VXFORM_ENV(vpkswus, 7, 5);
6743GEN_VXFORM_ENV(vpkshss, 7, 6);
6744GEN_VXFORM_ENV(vpkswss, 7, 7);
1dd9ffb9 6745GEN_VXFORM(vpkpx, 7, 12);
d15f74fb
BS
6746GEN_VXFORM_ENV(vsum4ubs, 4, 24);
6747GEN_VXFORM_ENV(vsum4sbs, 4, 28);
6748GEN_VXFORM_ENV(vsum4shs, 4, 25);
6749GEN_VXFORM_ENV(vsum2sws, 4, 26);
6750GEN_VXFORM_ENV(vsumsws, 4, 30);
6751GEN_VXFORM_ENV(vaddfp, 5, 0);
6752GEN_VXFORM_ENV(vsubfp, 5, 1);
6753GEN_VXFORM_ENV(vmaxfp, 5, 16);
6754GEN_VXFORM_ENV(vminfp, 5, 17);
fab3cbe9 6755
0cbcd906 6756#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
e8eaa2c0 6757static void glue(gen_, name)(DisasContext *ctx) \
0cbcd906
AJ
6758 { \
6759 TCGv_ptr ra, rb, rd; \
6760 if (unlikely(!ctx->altivec_enabled)) { \
6761 gen_exception(ctx, POWERPC_EXCP_VPU); \
6762 return; \
6763 } \
6764 ra = gen_avr_ptr(rA(ctx->opcode)); \
6765 rb = gen_avr_ptr(rB(ctx->opcode)); \
6766 rd = gen_avr_ptr(rD(ctx->opcode)); \
d15f74fb 6767 gen_helper_##opname(cpu_env, rd, ra, rb); \
0cbcd906
AJ
6768 tcg_temp_free_ptr(ra); \
6769 tcg_temp_free_ptr(rb); \
6770 tcg_temp_free_ptr(rd); \
6771 }
6772
6773#define GEN_VXRFORM(name, opc2, opc3) \
6774 GEN_VXRFORM1(name, name, #name, opc2, opc3) \
6775 GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
6776
1add6e23
AJ
6777GEN_VXRFORM(vcmpequb, 3, 0)
6778GEN_VXRFORM(vcmpequh, 3, 1)
6779GEN_VXRFORM(vcmpequw, 3, 2)
6780GEN_VXRFORM(vcmpgtsb, 3, 12)
6781GEN_VXRFORM(vcmpgtsh, 3, 13)
6782GEN_VXRFORM(vcmpgtsw, 3, 14)
6783GEN_VXRFORM(vcmpgtub, 3, 8)
6784GEN_VXRFORM(vcmpgtuh, 3, 9)
6785GEN_VXRFORM(vcmpgtuw, 3, 10)
819ca121
AJ
6786GEN_VXRFORM(vcmpeqfp, 3, 3)
6787GEN_VXRFORM(vcmpgefp, 3, 7)
6788GEN_VXRFORM(vcmpgtfp, 3, 11)
6789GEN_VXRFORM(vcmpbfp, 3, 15)
1add6e23 6790
c026766b 6791#define GEN_VXFORM_SIMM(name, opc2, opc3) \
99e300ef 6792static void glue(gen_, name)(DisasContext *ctx) \
c026766b
AJ
6793 { \
6794 TCGv_ptr rd; \
6795 TCGv_i32 simm; \
6796 if (unlikely(!ctx->altivec_enabled)) { \
6797 gen_exception(ctx, POWERPC_EXCP_VPU); \
6798 return; \
6799 } \
6800 simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6801 rd = gen_avr_ptr(rD(ctx->opcode)); \
6802 gen_helper_##name (rd, simm); \
6803 tcg_temp_free_i32(simm); \
6804 tcg_temp_free_ptr(rd); \
6805 }
6806
6807GEN_VXFORM_SIMM(vspltisb, 6, 12);
6808GEN_VXFORM_SIMM(vspltish, 6, 13);
6809GEN_VXFORM_SIMM(vspltisw, 6, 14);
6810
de5f2484 6811#define GEN_VXFORM_NOA(name, opc2, opc3) \
99e300ef 6812static void glue(gen_, name)(DisasContext *ctx) \
de5f2484
AJ
6813 { \
6814 TCGv_ptr rb, rd; \
6815 if (unlikely(!ctx->altivec_enabled)) { \
6816 gen_exception(ctx, POWERPC_EXCP_VPU); \
6817 return; \
6818 } \
6819 rb = gen_avr_ptr(rB(ctx->opcode)); \
6820 rd = gen_avr_ptr(rD(ctx->opcode)); \
6821 gen_helper_##name (rd, rb); \
6822 tcg_temp_free_ptr(rb); \
6823 tcg_temp_free_ptr(rd); \
6824 }
6825
d15f74fb
BS
6826#define GEN_VXFORM_NOA_ENV(name, opc2, opc3) \
6827static void glue(gen_, name)(DisasContext *ctx) \
6828 { \
6829 TCGv_ptr rb, rd; \
6830 \
6831 if (unlikely(!ctx->altivec_enabled)) { \
6832 gen_exception(ctx, POWERPC_EXCP_VPU); \
6833 return; \
6834 } \
6835 rb = gen_avr_ptr(rB(ctx->opcode)); \
6836 rd = gen_avr_ptr(rD(ctx->opcode)); \
6837 gen_helper_##name(cpu_env, rd, rb); \
6838 tcg_temp_free_ptr(rb); \
6839 tcg_temp_free_ptr(rd); \
6840 }
6841
6cf1c6e5
AJ
6842GEN_VXFORM_NOA(vupkhsb, 7, 8);
6843GEN_VXFORM_NOA(vupkhsh, 7, 9);
6844GEN_VXFORM_NOA(vupklsb, 7, 10);
6845GEN_VXFORM_NOA(vupklsh, 7, 11);
79f85c3a
AJ
6846GEN_VXFORM_NOA(vupkhpx, 7, 13);
6847GEN_VXFORM_NOA(vupklpx, 7, 15);
d15f74fb
BS
6848GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
6849GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
6850GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
6851GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
6852GEN_VXFORM_NOA_ENV(vrfim, 5, 8);
6853GEN_VXFORM_NOA_ENV(vrfin, 5, 9);
6854GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
6855GEN_VXFORM_NOA_ENV(vrfiz, 5, 11);
79f85c3a 6856
21d21583 6857#define GEN_VXFORM_SIMM(name, opc2, opc3) \
99e300ef 6858static void glue(gen_, name)(DisasContext *ctx) \
21d21583
AJ
6859 { \
6860 TCGv_ptr rd; \
6861 TCGv_i32 simm; \
6862 if (unlikely(!ctx->altivec_enabled)) { \
6863 gen_exception(ctx, POWERPC_EXCP_VPU); \
6864 return; \
6865 } \
6866 simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6867 rd = gen_avr_ptr(rD(ctx->opcode)); \
6868 gen_helper_##name (rd, simm); \
6869 tcg_temp_free_i32(simm); \
6870 tcg_temp_free_ptr(rd); \
6871 }
6872
27a4edb3 6873#define GEN_VXFORM_UIMM(name, opc2, opc3) \
99e300ef 6874static void glue(gen_, name)(DisasContext *ctx) \
27a4edb3
AJ
6875 { \
6876 TCGv_ptr rb, rd; \
6877 TCGv_i32 uimm; \
6878 if (unlikely(!ctx->altivec_enabled)) { \
6879 gen_exception(ctx, POWERPC_EXCP_VPU); \
6880 return; \
6881 } \
6882 uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
6883 rb = gen_avr_ptr(rB(ctx->opcode)); \
6884 rd = gen_avr_ptr(rD(ctx->opcode)); \
6885 gen_helper_##name (rd, rb, uimm); \
6886 tcg_temp_free_i32(uimm); \
6887 tcg_temp_free_ptr(rb); \
6888 tcg_temp_free_ptr(rd); \
6889 }
6890
d15f74fb
BS
6891#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3) \
6892static void glue(gen_, name)(DisasContext *ctx) \
6893 { \
6894 TCGv_ptr rb, rd; \
6895 TCGv_i32 uimm; \
6896 \
6897 if (unlikely(!ctx->altivec_enabled)) { \
6898 gen_exception(ctx, POWERPC_EXCP_VPU); \
6899 return; \
6900 } \
6901 uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
6902 rb = gen_avr_ptr(rB(ctx->opcode)); \
6903 rd = gen_avr_ptr(rD(ctx->opcode)); \
6904 gen_helper_##name(cpu_env, rd, rb, uimm); \
6905 tcg_temp_free_i32(uimm); \
6906 tcg_temp_free_ptr(rb); \
6907 tcg_temp_free_ptr(rd); \
6908 }
6909
e4e6bee7
AJ
6910GEN_VXFORM_UIMM(vspltb, 6, 8);
6911GEN_VXFORM_UIMM(vsplth, 6, 9);
6912GEN_VXFORM_UIMM(vspltw, 6, 10);
d15f74fb
BS
6913GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
6914GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
6915GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
6916GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
e4e6bee7 6917
99e300ef 6918static void gen_vsldoi(DisasContext *ctx)
cd633b10
AJ
6919{
6920 TCGv_ptr ra, rb, rd;
fce5ecb7 6921 TCGv_i32 sh;
cd633b10
AJ
6922 if (unlikely(!ctx->altivec_enabled)) {
6923 gen_exception(ctx, POWERPC_EXCP_VPU);
6924 return;
6925 }
6926 ra = gen_avr_ptr(rA(ctx->opcode));
6927 rb = gen_avr_ptr(rB(ctx->opcode));
6928 rd = gen_avr_ptr(rD(ctx->opcode));
6929 sh = tcg_const_i32(VSH(ctx->opcode));
6930 gen_helper_vsldoi (rd, ra, rb, sh);
6931 tcg_temp_free_ptr(ra);
6932 tcg_temp_free_ptr(rb);
6933 tcg_temp_free_ptr(rd);
fce5ecb7 6934 tcg_temp_free_i32(sh);
cd633b10
AJ
6935}
6936
707cec33 6937#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
d15f74fb 6938static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
707cec33
AJ
6939 { \
6940 TCGv_ptr ra, rb, rc, rd; \
6941 if (unlikely(!ctx->altivec_enabled)) { \
6942 gen_exception(ctx, POWERPC_EXCP_VPU); \
6943 return; \
6944 } \
6945 ra = gen_avr_ptr(rA(ctx->opcode)); \
6946 rb = gen_avr_ptr(rB(ctx->opcode)); \
6947 rc = gen_avr_ptr(rC(ctx->opcode)); \
6948 rd = gen_avr_ptr(rD(ctx->opcode)); \
6949 if (Rc(ctx->opcode)) { \
d15f74fb 6950 gen_helper_##name1(cpu_env, rd, ra, rb, rc); \
707cec33 6951 } else { \
d15f74fb 6952 gen_helper_##name0(cpu_env, rd, ra, rb, rc); \
707cec33
AJ
6953 } \
6954 tcg_temp_free_ptr(ra); \
6955 tcg_temp_free_ptr(rb); \
6956 tcg_temp_free_ptr(rc); \
6957 tcg_temp_free_ptr(rd); \
6958 }
6959
b161ae27
AJ
6960GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
6961
99e300ef 6962static void gen_vmladduhm(DisasContext *ctx)
bcd2ee23
AJ
6963{
6964 TCGv_ptr ra, rb, rc, rd;
6965 if (unlikely(!ctx->altivec_enabled)) {
6966 gen_exception(ctx, POWERPC_EXCP_VPU);
6967 return;
6968 }
6969 ra = gen_avr_ptr(rA(ctx->opcode));
6970 rb = gen_avr_ptr(rB(ctx->opcode));
6971 rc = gen_avr_ptr(rC(ctx->opcode));
6972 rd = gen_avr_ptr(rD(ctx->opcode));
6973 gen_helper_vmladduhm(rd, ra, rb, rc);
6974 tcg_temp_free_ptr(ra);
6975 tcg_temp_free_ptr(rb);
6976 tcg_temp_free_ptr(rc);
6977 tcg_temp_free_ptr(rd);
6978}
6979
b04ae981 6980GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
4d9903b6 6981GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
eae07261 6982GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
d1258698 6983GEN_VAFORM_PAIRED(vsel, vperm, 21)
35cf7c7e 6984GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
b04ae981 6985
472b24ce
TM
6986/*** VSX extension ***/
6987
6988static inline TCGv_i64 cpu_vsrh(int n)
6989{
6990 if (n < 32) {
6991 return cpu_fpr[n];
6992 } else {
6993 return cpu_avrh[n-32];
6994 }
6995}
6996
6997static inline TCGv_i64 cpu_vsrl(int n)
6998{
6999 if (n < 32) {
7000 return cpu_vsr[n];
7001 } else {
7002 return cpu_avrl[n-32];
7003 }
7004}
7005
fa1832d7
TM
7006static void gen_lxsdx(DisasContext *ctx)
7007{
7008 TCGv EA;
7009 if (unlikely(!ctx->vsx_enabled)) {
7010 gen_exception(ctx, POWERPC_EXCP_VSXU);
7011 return;
7012 }
7013 gen_set_access_type(ctx, ACCESS_INT);
7014 EA = tcg_temp_new();
7015 gen_addr_reg_index(ctx, EA);
7016 gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
7017 /* NOTE: cpu_vsrl is undefined */
7018 tcg_temp_free(EA);
7019}
7020
304af367
TM
7021static void gen_lxvd2x(DisasContext *ctx)
7022{
7023 TCGv EA;
7024 if (unlikely(!ctx->vsx_enabled)) {
7025 gen_exception(ctx, POWERPC_EXCP_VSXU);
7026 return;
7027 }
7028 gen_set_access_type(ctx, ACCESS_INT);
7029 EA = tcg_temp_new();
7030 gen_addr_reg_index(ctx, EA);
7031 gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
7032 tcg_gen_addi_tl(EA, EA, 8);
7033 gen_qemu_ld64(ctx, cpu_vsrl(xT(ctx->opcode)), EA);
7034 tcg_temp_free(EA);
7035}
7036
ca03b467
TM
7037static void gen_lxvdsx(DisasContext *ctx)
7038{
7039 TCGv EA;
7040 if (unlikely(!ctx->vsx_enabled)) {
7041 gen_exception(ctx, POWERPC_EXCP_VSXU);
7042 return;
7043 }
7044 gen_set_access_type(ctx, ACCESS_INT);
7045 EA = tcg_temp_new();
7046 gen_addr_reg_index(ctx, EA);
7047 gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
7048 tcg_gen_mov_tl(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
7049 tcg_temp_free(EA);
7050}
7051
897e61d1
TM
7052static void gen_lxvw4x(DisasContext *ctx)
7053{
7054 TCGv EA, tmp;
7055 TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
7056 TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
7057 if (unlikely(!ctx->vsx_enabled)) {
7058 gen_exception(ctx, POWERPC_EXCP_VSXU);
7059 return;
7060 }
7061 gen_set_access_type(ctx, ACCESS_INT);
7062 EA = tcg_temp_new();
7063 tmp = tcg_temp_new();
7064 gen_addr_reg_index(ctx, EA);
7065 gen_qemu_ld32u(ctx, tmp, EA);
7066 tcg_gen_addi_tl(EA, EA, 4);
7067 gen_qemu_ld32u(ctx, xth, EA);
7068 tcg_gen_deposit_i64(xth, xth, tmp, 32, 32);
7069
7070 tcg_gen_addi_tl(EA, EA, 4);
7071 gen_qemu_ld32u(ctx, tmp, EA);
7072 tcg_gen_addi_tl(EA, EA, 4);
7073 gen_qemu_ld32u(ctx, xtl, EA);
7074 tcg_gen_deposit_i64(xtl, xtl, tmp, 32, 32);
7075
7076 tcg_temp_free(EA);
7077 tcg_temp_free(tmp);
7078}
7079
9231ba9e
TM
7080static void gen_stxsdx(DisasContext *ctx)
7081{
7082 TCGv EA;
7083 if (unlikely(!ctx->vsx_enabled)) {
7084 gen_exception(ctx, POWERPC_EXCP_VSXU);
7085 return;
7086 }
7087 gen_set_access_type(ctx, ACCESS_INT);
7088 EA = tcg_temp_new();
7089 gen_addr_reg_index(ctx, EA);
7090 gen_qemu_st64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
7091 tcg_temp_free(EA);
7092}
7093
fbed2478
TM
7094static void gen_stxvd2x(DisasContext *ctx)
7095{
7096 TCGv EA;
7097 if (unlikely(!ctx->vsx_enabled)) {
7098 gen_exception(ctx, POWERPC_EXCP_VSXU);
7099 return;
7100 }
7101 gen_set_access_type(ctx, ACCESS_INT);
7102 EA = tcg_temp_new();
7103 gen_addr_reg_index(ctx, EA);
7104 gen_qemu_st64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
7105 tcg_gen_addi_tl(EA, EA, 8);
7106 gen_qemu_st64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
7107 tcg_temp_free(EA);
7108}
7109
86e61ce3
TM
7110static void gen_stxvw4x(DisasContext *ctx)
7111{
7112 TCGv EA, tmp;
7113 if (unlikely(!ctx->vsx_enabled)) {
7114 gen_exception(ctx, POWERPC_EXCP_VSXU);
7115 return;
7116 }
7117 gen_set_access_type(ctx, ACCESS_INT);
7118 EA = tcg_temp_new();
7119 gen_addr_reg_index(ctx, EA);
7120 tmp = tcg_temp_new();
7121
7122 tcg_gen_shri_i64(tmp, cpu_vsrh(xS(ctx->opcode)), 32);
7123 gen_qemu_st32(ctx, tmp, EA);
7124 tcg_gen_addi_tl(EA, EA, 4);
7125 gen_qemu_st32(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
7126
7127 tcg_gen_shri_i64(tmp, cpu_vsrl(xS(ctx->opcode)), 32);
7128 tcg_gen_addi_tl(EA, EA, 4);
7129 gen_qemu_st32(ctx, tmp, EA);
7130 tcg_gen_addi_tl(EA, EA, 4);
7131 gen_qemu_st32(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
7132
7133 tcg_temp_free(EA);
7134 tcg_temp_free(tmp);
7135}
7136
cd73f2c9
TM
7137static void gen_xxpermdi(DisasContext *ctx)
7138{
7139 if (unlikely(!ctx->vsx_enabled)) {
7140 gen_exception(ctx, POWERPC_EXCP_VSXU);
7141 return;
7142 }
7143
7144 if ((DM(ctx->opcode) & 2) == 0) {
7145 tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)));
7146 } else {
7147 tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)));
7148 }
7149 if ((DM(ctx->opcode) & 1) == 0) {
7150 tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xB(ctx->opcode)));
7151 } else {
7152 tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xB(ctx->opcode)));
7153 }
7154}
7155
df020ce0
TM
7156#define OP_ABS 1
7157#define OP_NABS 2
7158#define OP_NEG 3
7159#define OP_CPSGN 4
7160#define SGN_MASK_DP 0x8000000000000000ul
7161#define SGN_MASK_SP 0x8000000080000000ul
7162
7163#define VSX_SCALAR_MOVE(name, op, sgn_mask) \
7164static void glue(gen_, name)(DisasContext * ctx) \
7165 { \
7166 TCGv_i64 xb, sgm; \
7167 if (unlikely(!ctx->vsx_enabled)) { \
7168 gen_exception(ctx, POWERPC_EXCP_VSXU); \
7169 return; \
7170 } \
7171 xb = tcg_temp_new(); \
7172 sgm = tcg_temp_new(); \
7173 tcg_gen_mov_i64(xb, cpu_vsrh(xB(ctx->opcode))); \
7174 tcg_gen_movi_i64(sgm, sgn_mask); \
7175 switch (op) { \
7176 case OP_ABS: { \
7177 tcg_gen_andc_i64(xb, xb, sgm); \
7178 break; \
7179 } \
7180 case OP_NABS: { \
7181 tcg_gen_or_i64(xb, xb, sgm); \
7182 break; \
7183 } \
7184 case OP_NEG: { \
7185 tcg_gen_xor_i64(xb, xb, sgm); \
7186 break; \
7187 } \
7188 case OP_CPSGN: { \
7189 TCGv_i64 xa = tcg_temp_new(); \
7190 tcg_gen_mov_i64(xa, cpu_vsrh(xA(ctx->opcode))); \
7191 tcg_gen_and_i64(xa, xa, sgm); \
7192 tcg_gen_andc_i64(xb, xb, sgm); \
7193 tcg_gen_or_i64(xb, xb, xa); \
7194 tcg_temp_free(xa); \
7195 break; \
7196 } \
7197 } \
7198 tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xb); \
7199 tcg_temp_free(xb); \
7200 tcg_temp_free(sgm); \
7201 }
7202
7203VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP)
7204VSX_SCALAR_MOVE(xsnabsdp, OP_NABS, SGN_MASK_DP)
7205VSX_SCALAR_MOVE(xsnegdp, OP_NEG, SGN_MASK_DP)
7206VSX_SCALAR_MOVE(xscpsgndp, OP_CPSGN, SGN_MASK_DP)
7207
7208
0487d6a8 7209/*** SPE extension ***/
0487d6a8 7210/* Register moves */
3cd7d1dd 7211
a0e13900
FC
7212static inline void gen_evmra(DisasContext *ctx)
7213{
7214
7215 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7216 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
7217 return;
7218 }
7219
7220#if defined(TARGET_PPC64)
7221 /* rD := rA */
7222 tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7223
7224 /* spe_acc := rA */
7225 tcg_gen_st_i64(cpu_gpr[rA(ctx->opcode)],
7226 cpu_env,
1328c2bf 7227 offsetof(CPUPPCState, spe_acc));
a0e13900
FC
7228#else
7229 TCGv_i64 tmp = tcg_temp_new_i64();
7230
7231 /* tmp := rA_lo + rA_hi << 32 */
7232 tcg_gen_concat_i32_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7233
7234 /* spe_acc := tmp */
1328c2bf 7235 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
7236 tcg_temp_free_i64(tmp);
7237
7238 /* rD := rA */
7239 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7240 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7241#endif
7242}
7243
636aa200
BS
7244static inline void gen_load_gpr64(TCGv_i64 t, int reg)
7245{
f78fb44e
AJ
7246#if defined(TARGET_PPC64)
7247 tcg_gen_mov_i64(t, cpu_gpr[reg]);
7248#else
36aa55dc 7249 tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
3cd7d1dd 7250#endif
f78fb44e 7251}
3cd7d1dd 7252
636aa200
BS
7253static inline void gen_store_gpr64(int reg, TCGv_i64 t)
7254{
f78fb44e
AJ
7255#if defined(TARGET_PPC64)
7256 tcg_gen_mov_i64(cpu_gpr[reg], t);
7257#else
a7812ae4 7258 TCGv_i64 tmp = tcg_temp_new_i64();
f78fb44e 7259 tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
f78fb44e
AJ
7260 tcg_gen_shri_i64(tmp, t, 32);
7261 tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
a7812ae4 7262 tcg_temp_free_i64(tmp);
3cd7d1dd 7263#endif
f78fb44e 7264}
3cd7d1dd 7265
70560da7 7266#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
99e300ef 7267static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
0487d6a8
JM
7268{ \
7269 if (Rc(ctx->opcode)) \
7270 gen_##name1(ctx); \
7271 else \
7272 gen_##name0(ctx); \
7273}
7274
7275/* Handler for undefined SPE opcodes */
636aa200 7276static inline void gen_speundef(DisasContext *ctx)
0487d6a8 7277{
e06fcd75 7278 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
0487d6a8
JM
7279}
7280
57951c27
AJ
7281/* SPE logic */
7282#if defined(TARGET_PPC64)
7283#define GEN_SPEOP_LOGIC2(name, tcg_op) \
636aa200 7284static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
7285{ \
7286 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7287 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
7288 return; \
7289 } \
57951c27
AJ
7290 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7291 cpu_gpr[rB(ctx->opcode)]); \
7292}
7293#else
7294#define GEN_SPEOP_LOGIC2(name, tcg_op) \
636aa200 7295static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7296{ \
7297 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7298 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7299 return; \
7300 } \
7301 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7302 cpu_gpr[rB(ctx->opcode)]); \
7303 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
7304 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 7305}
57951c27
AJ
7306#endif
7307
7308GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
7309GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
7310GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
7311GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
7312GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
7313GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
7314GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
7315GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
0487d6a8 7316
57951c27
AJ
7317/* SPE logic immediate */
7318#if defined(TARGET_PPC64)
7319#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
636aa200 7320static inline void gen_##name(DisasContext *ctx) \
3d3a6a0a
AJ
7321{ \
7322 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7323 gen_exception(ctx, POWERPC_EXCP_SPEU); \
3d3a6a0a
AJ
7324 return; \
7325 } \
a7812ae4
PB
7326 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
7327 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
7328 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
7329 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7330 tcg_opi(t0, t0, rB(ctx->opcode)); \
7331 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
7332 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 7333 tcg_temp_free_i64(t2); \
57951c27
AJ
7334 tcg_opi(t1, t1, rB(ctx->opcode)); \
7335 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
7336 tcg_temp_free_i32(t0); \
7337 tcg_temp_free_i32(t1); \
3d3a6a0a 7338}
57951c27
AJ
7339#else
7340#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
636aa200 7341static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
7342{ \
7343 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7344 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
7345 return; \
7346 } \
57951c27
AJ
7347 tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7348 rB(ctx->opcode)); \
7349 tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
7350 rB(ctx->opcode)); \
0487d6a8 7351}
57951c27
AJ
7352#endif
7353GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
7354GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
7355GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
7356GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
0487d6a8 7357
57951c27
AJ
7358/* SPE arithmetic */
7359#if defined(TARGET_PPC64)
7360#define GEN_SPEOP_ARITH1(name, tcg_op) \
636aa200 7361static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
7362{ \
7363 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7364 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
7365 return; \
7366 } \
a7812ae4
PB
7367 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
7368 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
7369 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
7370 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7371 tcg_op(t0, t0); \
7372 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
7373 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 7374 tcg_temp_free_i64(t2); \
57951c27
AJ
7375 tcg_op(t1, t1); \
7376 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
7377 tcg_temp_free_i32(t0); \
7378 tcg_temp_free_i32(t1); \
0487d6a8 7379}
57951c27 7380#else
a7812ae4 7381#define GEN_SPEOP_ARITH1(name, tcg_op) \
636aa200 7382static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7383{ \
7384 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7385 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7386 return; \
7387 } \
7388 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
7389 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
7390}
7391#endif
0487d6a8 7392
636aa200 7393static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
57951c27
AJ
7394{
7395 int l1 = gen_new_label();
7396 int l2 = gen_new_label();
0487d6a8 7397
57951c27
AJ
7398 tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
7399 tcg_gen_neg_i32(ret, arg1);
7400 tcg_gen_br(l2);
7401 gen_set_label(l1);
a7812ae4 7402 tcg_gen_mov_i32(ret, arg1);
57951c27
AJ
7403 gen_set_label(l2);
7404}
7405GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
7406GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
7407GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
7408GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
636aa200 7409static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
0487d6a8 7410{
57951c27
AJ
7411 tcg_gen_addi_i32(ret, arg1, 0x8000);
7412 tcg_gen_ext16u_i32(ret, ret);
7413}
7414GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
a7812ae4
PB
7415GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
7416GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
0487d6a8 7417
57951c27
AJ
7418#if defined(TARGET_PPC64)
7419#define GEN_SPEOP_ARITH2(name, tcg_op) \
636aa200 7420static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
7421{ \
7422 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7423 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
7424 return; \
7425 } \
a7812ae4
PB
7426 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
7427 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
7428 TCGv_i32 t2 = tcg_temp_local_new_i32(); \
501e23c4 7429 TCGv_i64 t3 = tcg_temp_local_new_i64(); \
57951c27
AJ
7430 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7431 tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
7432 tcg_op(t0, t0, t2); \
7433 tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
7434 tcg_gen_trunc_i64_i32(t1, t3); \
7435 tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
7436 tcg_gen_trunc_i64_i32(t2, t3); \
a7812ae4 7437 tcg_temp_free_i64(t3); \
57951c27 7438 tcg_op(t1, t1, t2); \
a7812ae4 7439 tcg_temp_free_i32(t2); \
57951c27 7440 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
7441 tcg_temp_free_i32(t0); \
7442 tcg_temp_free_i32(t1); \
0487d6a8 7443}
57951c27
AJ
7444#else
7445#define GEN_SPEOP_ARITH2(name, tcg_op) \
636aa200 7446static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
7447{ \
7448 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7449 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
7450 return; \
7451 } \
57951c27
AJ
7452 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7453 cpu_gpr[rB(ctx->opcode)]); \
7454 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
7455 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 7456}
57951c27 7457#endif
0487d6a8 7458
636aa200 7459static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 7460{
a7812ae4 7461 TCGv_i32 t0;
57951c27 7462 int l1, l2;
0487d6a8 7463
57951c27
AJ
7464 l1 = gen_new_label();
7465 l2 = gen_new_label();
a7812ae4 7466 t0 = tcg_temp_local_new_i32();
57951c27
AJ
7467 /* No error here: 6 bits are used */
7468 tcg_gen_andi_i32(t0, arg2, 0x3F);
7469 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
7470 tcg_gen_shr_i32(ret, arg1, t0);
7471 tcg_gen_br(l2);
7472 gen_set_label(l1);
7473 tcg_gen_movi_i32(ret, 0);
0aef4261 7474 gen_set_label(l2);
a7812ae4 7475 tcg_temp_free_i32(t0);
57951c27
AJ
7476}
7477GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
636aa200 7478static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 7479{
a7812ae4 7480 TCGv_i32 t0;
57951c27
AJ
7481 int l1, l2;
7482
7483 l1 = gen_new_label();
7484 l2 = gen_new_label();
a7812ae4 7485 t0 = tcg_temp_local_new_i32();
57951c27
AJ
7486 /* No error here: 6 bits are used */
7487 tcg_gen_andi_i32(t0, arg2, 0x3F);
7488 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
7489 tcg_gen_sar_i32(ret, arg1, t0);
7490 tcg_gen_br(l2);
7491 gen_set_label(l1);
7492 tcg_gen_movi_i32(ret, 0);
0aef4261 7493 gen_set_label(l2);
a7812ae4 7494 tcg_temp_free_i32(t0);
57951c27
AJ
7495}
7496GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
636aa200 7497static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 7498{
a7812ae4 7499 TCGv_i32 t0;
57951c27
AJ
7500 int l1, l2;
7501
7502 l1 = gen_new_label();
7503 l2 = gen_new_label();
a7812ae4 7504 t0 = tcg_temp_local_new_i32();
57951c27
AJ
7505 /* No error here: 6 bits are used */
7506 tcg_gen_andi_i32(t0, arg2, 0x3F);
7507 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
7508 tcg_gen_shl_i32(ret, arg1, t0);
7509 tcg_gen_br(l2);
7510 gen_set_label(l1);
7511 tcg_gen_movi_i32(ret, 0);
e29ef9fa 7512 gen_set_label(l2);
a7812ae4 7513 tcg_temp_free_i32(t0);
57951c27
AJ
7514}
7515GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
636aa200 7516static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 7517{
a7812ae4 7518 TCGv_i32 t0 = tcg_temp_new_i32();
57951c27
AJ
7519 tcg_gen_andi_i32(t0, arg2, 0x1F);
7520 tcg_gen_rotl_i32(ret, arg1, t0);
a7812ae4 7521 tcg_temp_free_i32(t0);
57951c27
AJ
7522}
7523GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
636aa200 7524static inline void gen_evmergehi(DisasContext *ctx)
57951c27
AJ
7525{
7526 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7527 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
7528 return;
7529 }
7530#if defined(TARGET_PPC64)
a7812ae4
PB
7531 TCGv t0 = tcg_temp_new();
7532 TCGv t1 = tcg_temp_new();
57951c27
AJ
7533 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
7534 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
7535 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7536 tcg_temp_free(t0);
7537 tcg_temp_free(t1);
7538#else
7539 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7540 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7541#endif
7542}
7543GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
636aa200 7544static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
0487d6a8 7545{
57951c27
AJ
7546 tcg_gen_sub_i32(ret, arg2, arg1);
7547}
7548GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
0487d6a8 7549
57951c27
AJ
7550/* SPE arithmetic immediate */
7551#if defined(TARGET_PPC64)
7552#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
636aa200 7553static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7554{ \
7555 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7556 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7557 return; \
7558 } \
a7812ae4
PB
7559 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
7560 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
7561 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
7562 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7563 tcg_op(t0, t0, rA(ctx->opcode)); \
7564 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
7565 tcg_gen_trunc_i64_i32(t1, t2); \
e06fcd75 7566 tcg_temp_free_i64(t2); \
57951c27
AJ
7567 tcg_op(t1, t1, rA(ctx->opcode)); \
7568 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
7569 tcg_temp_free_i32(t0); \
7570 tcg_temp_free_i32(t1); \
57951c27
AJ
7571}
7572#else
7573#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
636aa200 7574static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7575{ \
7576 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7577 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7578 return; \
7579 } \
7580 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
7581 rA(ctx->opcode)); \
7582 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
7583 rA(ctx->opcode)); \
7584}
7585#endif
7586GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
7587GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
7588
7589/* SPE comparison */
7590#if defined(TARGET_PPC64)
7591#define GEN_SPEOP_COMP(name, tcg_cond) \
636aa200 7592static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7593{ \
7594 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7595 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7596 return; \
7597 } \
7598 int l1 = gen_new_label(); \
7599 int l2 = gen_new_label(); \
7600 int l3 = gen_new_label(); \
7601 int l4 = gen_new_label(); \
a7812ae4
PB
7602 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
7603 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
7604 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
7605 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7606 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7607 tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
a7812ae4 7608 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
57951c27
AJ
7609 tcg_gen_br(l2); \
7610 gen_set_label(l1); \
7611 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
7612 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
7613 gen_set_label(l2); \
7614 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
7615 tcg_gen_trunc_i64_i32(t0, t2); \
7616 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
7617 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 7618 tcg_temp_free_i64(t2); \
57951c27
AJ
7619 tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
7620 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7621 ~(CRF_CH | CRF_CH_AND_CL)); \
7622 tcg_gen_br(l4); \
7623 gen_set_label(l3); \
7624 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7625 CRF_CH | CRF_CH_OR_CL); \
7626 gen_set_label(l4); \
a7812ae4
PB
7627 tcg_temp_free_i32(t0); \
7628 tcg_temp_free_i32(t1); \
57951c27
AJ
7629}
7630#else
7631#define GEN_SPEOP_COMP(name, tcg_cond) \
636aa200 7632static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7633{ \
7634 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7635 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7636 return; \
7637 } \
7638 int l1 = gen_new_label(); \
7639 int l2 = gen_new_label(); \
7640 int l3 = gen_new_label(); \
7641 int l4 = gen_new_label(); \
7642 \
7643 tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
7644 cpu_gpr[rB(ctx->opcode)], l1); \
7645 tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
7646 tcg_gen_br(l2); \
7647 gen_set_label(l1); \
7648 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
7649 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
7650 gen_set_label(l2); \
7651 tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
7652 cpu_gprh[rB(ctx->opcode)], l3); \
7653 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7654 ~(CRF_CH | CRF_CH_AND_CL)); \
7655 tcg_gen_br(l4); \
7656 gen_set_label(l3); \
7657 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7658 CRF_CH | CRF_CH_OR_CL); \
7659 gen_set_label(l4); \
7660}
7661#endif
7662GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
7663GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
7664GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
7665GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
7666GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
7667
7668/* SPE misc */
636aa200 7669static inline void gen_brinc(DisasContext *ctx)
57951c27
AJ
7670{
7671 /* Note: brinc is usable even if SPE is disabled */
a7812ae4
PB
7672 gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
7673 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
0487d6a8 7674}
636aa200 7675static inline void gen_evmergelo(DisasContext *ctx)
57951c27
AJ
7676{
7677 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7678 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
7679 return;
7680 }
7681#if defined(TARGET_PPC64)
a7812ae4
PB
7682 TCGv t0 = tcg_temp_new();
7683 TCGv t1 = tcg_temp_new();
17d9b3af 7684 tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
57951c27
AJ
7685 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
7686 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7687 tcg_temp_free(t0);
7688 tcg_temp_free(t1);
7689#else
57951c27 7690 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
33890b3e 7691 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
57951c27
AJ
7692#endif
7693}
636aa200 7694static inline void gen_evmergehilo(DisasContext *ctx)
57951c27
AJ
7695{
7696 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7697 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
7698 return;
7699 }
7700#if defined(TARGET_PPC64)
a7812ae4
PB
7701 TCGv t0 = tcg_temp_new();
7702 TCGv t1 = tcg_temp_new();
17d9b3af 7703 tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
57951c27
AJ
7704 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
7705 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7706 tcg_temp_free(t0);
7707 tcg_temp_free(t1);
7708#else
7709 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7710 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7711#endif
7712}
636aa200 7713static inline void gen_evmergelohi(DisasContext *ctx)
57951c27
AJ
7714{
7715 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7716 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
7717 return;
7718 }
7719#if defined(TARGET_PPC64)
a7812ae4
PB
7720 TCGv t0 = tcg_temp_new();
7721 TCGv t1 = tcg_temp_new();
57951c27
AJ
7722 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
7723 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
7724 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7725 tcg_temp_free(t0);
7726 tcg_temp_free(t1);
7727#else
33890b3e
NF
7728 if (rD(ctx->opcode) == rA(ctx->opcode)) {
7729 TCGv_i32 tmp = tcg_temp_new_i32();
7730 tcg_gen_mov_i32(tmp, cpu_gpr[rA(ctx->opcode)]);
7731 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7732 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], tmp);
7733 tcg_temp_free_i32(tmp);
7734 } else {
7735 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7736 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7737 }
57951c27
AJ
7738#endif
7739}
636aa200 7740static inline void gen_evsplati(DisasContext *ctx)
57951c27 7741{
ae01847f 7742 uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
0487d6a8 7743
57951c27 7744#if defined(TARGET_PPC64)
38d14952 7745 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
7746#else
7747 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7748 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7749#endif
7750}
636aa200 7751static inline void gen_evsplatfi(DisasContext *ctx)
0487d6a8 7752{
ae01847f 7753 uint64_t imm = rA(ctx->opcode) << 27;
0487d6a8 7754
57951c27 7755#if defined(TARGET_PPC64)
38d14952 7756 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
7757#else
7758 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7759 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7760#endif
0487d6a8
JM
7761}
7762
636aa200 7763static inline void gen_evsel(DisasContext *ctx)
57951c27
AJ
7764{
7765 int l1 = gen_new_label();
7766 int l2 = gen_new_label();
7767 int l3 = gen_new_label();
7768 int l4 = gen_new_label();
a7812ae4 7769 TCGv_i32 t0 = tcg_temp_local_new_i32();
57951c27 7770#if defined(TARGET_PPC64)
a7812ae4
PB
7771 TCGv t1 = tcg_temp_local_new();
7772 TCGv t2 = tcg_temp_local_new();
57951c27
AJ
7773#endif
7774 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
7775 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
7776#if defined(TARGET_PPC64)
7777 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7778#else
7779 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7780#endif
7781 tcg_gen_br(l2);
7782 gen_set_label(l1);
7783#if defined(TARGET_PPC64)
7784 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7785#else
7786 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7787#endif
7788 gen_set_label(l2);
7789 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
7790 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
7791#if defined(TARGET_PPC64)
17d9b3af 7792 tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
57951c27
AJ
7793#else
7794 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7795#endif
7796 tcg_gen_br(l4);
7797 gen_set_label(l3);
7798#if defined(TARGET_PPC64)
17d9b3af 7799 tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
57951c27
AJ
7800#else
7801 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7802#endif
7803 gen_set_label(l4);
a7812ae4 7804 tcg_temp_free_i32(t0);
57951c27
AJ
7805#if defined(TARGET_PPC64)
7806 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
7807 tcg_temp_free(t1);
7808 tcg_temp_free(t2);
7809#endif
7810}
e8eaa2c0
BS
7811
7812static void gen_evsel0(DisasContext *ctx)
57951c27
AJ
7813{
7814 gen_evsel(ctx);
7815}
e8eaa2c0
BS
7816
7817static void gen_evsel1(DisasContext *ctx)
57951c27
AJ
7818{
7819 gen_evsel(ctx);
7820}
e8eaa2c0
BS
7821
7822static void gen_evsel2(DisasContext *ctx)
57951c27
AJ
7823{
7824 gen_evsel(ctx);
7825}
e8eaa2c0
BS
7826
7827static void gen_evsel3(DisasContext *ctx)
57951c27
AJ
7828{
7829 gen_evsel(ctx);
7830}
0487d6a8 7831
a0e13900
FC
7832/* Multiply */
7833
7834static inline void gen_evmwumi(DisasContext *ctx)
7835{
7836 TCGv_i64 t0, t1;
7837
7838 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7839 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
7840 return;
7841 }
7842
7843 t0 = tcg_temp_new_i64();
7844 t1 = tcg_temp_new_i64();
7845
7846 /* t0 := rA; t1 := rB */
7847#if defined(TARGET_PPC64)
7848 tcg_gen_ext32u_tl(t0, cpu_gpr[rA(ctx->opcode)]);
7849 tcg_gen_ext32u_tl(t1, cpu_gpr[rB(ctx->opcode)]);
7850#else
7851 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
7852 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
7853#endif
7854
7855 tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
7856
7857 gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
7858
7859 tcg_temp_free_i64(t0);
7860 tcg_temp_free_i64(t1);
7861}
7862
7863static inline void gen_evmwumia(DisasContext *ctx)
7864{
7865 TCGv_i64 tmp;
7866
7867 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7868 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
7869 return;
7870 }
7871
7872 gen_evmwumi(ctx); /* rD := rA * rB */
7873
7874 tmp = tcg_temp_new_i64();
7875
7876 /* acc := rD */
7877 gen_load_gpr64(tmp, rD(ctx->opcode));
1328c2bf 7878 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
7879 tcg_temp_free_i64(tmp);
7880}
7881
7882static inline void gen_evmwumiaa(DisasContext *ctx)
7883{
7884 TCGv_i64 acc;
7885 TCGv_i64 tmp;
7886
7887 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7888 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
7889 return;
7890 }
7891
7892 gen_evmwumi(ctx); /* rD := rA * rB */
7893
7894 acc = tcg_temp_new_i64();
7895 tmp = tcg_temp_new_i64();
7896
7897 /* tmp := rD */
7898 gen_load_gpr64(tmp, rD(ctx->opcode));
7899
7900 /* Load acc */
1328c2bf 7901 tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
7902
7903 /* acc := tmp + acc */
7904 tcg_gen_add_i64(acc, acc, tmp);
7905
7906 /* Store acc */
1328c2bf 7907 tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
7908
7909 /* rD := acc */
7910 gen_store_gpr64(rD(ctx->opcode), acc);
7911
7912 tcg_temp_free_i64(acc);
7913 tcg_temp_free_i64(tmp);
7914}
7915
7916static inline void gen_evmwsmi(DisasContext *ctx)
7917{
7918 TCGv_i64 t0, t1;
7919
7920 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7921 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
7922 return;
7923 }
7924
7925 t0 = tcg_temp_new_i64();
7926 t1 = tcg_temp_new_i64();
7927
7928 /* t0 := rA; t1 := rB */
7929#if defined(TARGET_PPC64)
7930 tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
7931 tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
7932#else
7933 tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
7934 tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
7935#endif
7936
7937 tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
7938
7939 gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
7940
7941 tcg_temp_free_i64(t0);
7942 tcg_temp_free_i64(t1);
7943}
7944
7945static inline void gen_evmwsmia(DisasContext *ctx)
7946{
7947 TCGv_i64 tmp;
7948
7949 gen_evmwsmi(ctx); /* rD := rA * rB */
7950
7951 tmp = tcg_temp_new_i64();
7952
7953 /* acc := rD */
7954 gen_load_gpr64(tmp, rD(ctx->opcode));
1328c2bf 7955 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
7956
7957 tcg_temp_free_i64(tmp);
7958}
7959
7960static inline void gen_evmwsmiaa(DisasContext *ctx)
7961{
7962 TCGv_i64 acc = tcg_temp_new_i64();
7963 TCGv_i64 tmp = tcg_temp_new_i64();
7964
7965 gen_evmwsmi(ctx); /* rD := rA * rB */
7966
7967 acc = tcg_temp_new_i64();
7968 tmp = tcg_temp_new_i64();
7969
7970 /* tmp := rD */
7971 gen_load_gpr64(tmp, rD(ctx->opcode));
7972
7973 /* Load acc */
1328c2bf 7974 tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
7975
7976 /* acc := tmp + acc */
7977 tcg_gen_add_i64(acc, acc, tmp);
7978
7979 /* Store acc */
1328c2bf 7980 tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
a0e13900
FC
7981
7982 /* rD := acc */
7983 gen_store_gpr64(rD(ctx->opcode), acc);
7984
7985 tcg_temp_free_i64(acc);
7986 tcg_temp_free_i64(tmp);
7987}
7988
70560da7
FC
7989GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
7990GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
7991GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
7992GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
7993GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
7994GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
7995GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); ////
7996GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE); //
7997GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE);
7998GEN_SPE(speundef, evand, 0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
7999GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
8000GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
8001GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
8002GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
8003GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE);
8004GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE);
8005GEN_SPE(speundef, evorc, 0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); ////
8006GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
8007GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
8008GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE);
8009GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
8010GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE);
8011GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE); //
8012GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE);
8013GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
8014GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE); ////
8015GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
8016GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE); ////
8017GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE); ////
0487d6a8 8018
6a6ae23f 8019/* SPE load and stores */
636aa200 8020static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
6a6ae23f
AJ
8021{
8022 target_ulong uimm = rB(ctx->opcode);
8023
76db3ba4 8024 if (rA(ctx->opcode) == 0) {
6a6ae23f 8025 tcg_gen_movi_tl(EA, uimm << sh);
76db3ba4 8026 } else {
6a6ae23f 8027 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
c791fe84 8028 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
8029 tcg_gen_ext32u_tl(EA, EA);
8030 }
76db3ba4 8031 }
0487d6a8 8032}
6a6ae23f 8033
636aa200 8034static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8035{
8036#if defined(TARGET_PPC64)
76db3ba4 8037 gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f
AJ
8038#else
8039 TCGv_i64 t0 = tcg_temp_new_i64();
76db3ba4 8040 gen_qemu_ld64(ctx, t0, addr);
6a6ae23f
AJ
8041 tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
8042 tcg_gen_shri_i64(t0, t0, 32);
8043 tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
8044 tcg_temp_free_i64(t0);
8045#endif
0487d6a8 8046}
6a6ae23f 8047
636aa200 8048static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
6a6ae23f 8049{
0487d6a8 8050#if defined(TARGET_PPC64)
6a6ae23f 8051 TCGv t0 = tcg_temp_new();
76db3ba4 8052 gen_qemu_ld32u(ctx, t0, addr);
6a6ae23f 8053 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
76db3ba4
AJ
8054 gen_addr_add(ctx, addr, addr, 4);
8055 gen_qemu_ld32u(ctx, t0, addr);
6a6ae23f
AJ
8056 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8057 tcg_temp_free(t0);
8058#else
76db3ba4
AJ
8059 gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
8060 gen_addr_add(ctx, addr, addr, 4);
8061 gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f 8062#endif
0487d6a8 8063}
6a6ae23f 8064
636aa200 8065static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8066{
8067 TCGv t0 = tcg_temp_new();
8068#if defined(TARGET_PPC64)
76db3ba4 8069 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 8070 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
76db3ba4
AJ
8071 gen_addr_add(ctx, addr, addr, 2);
8072 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8073 tcg_gen_shli_tl(t0, t0, 32);
8074 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
76db3ba4
AJ
8075 gen_addr_add(ctx, addr, addr, 2);
8076 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8077 tcg_gen_shli_tl(t0, t0, 16);
8078 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
76db3ba4
AJ
8079 gen_addr_add(ctx, addr, addr, 2);
8080 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 8081 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 8082#else
76db3ba4 8083 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 8084 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
76db3ba4
AJ
8085 gen_addr_add(ctx, addr, addr, 2);
8086 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 8087 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
76db3ba4
AJ
8088 gen_addr_add(ctx, addr, addr, 2);
8089 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 8090 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
76db3ba4
AJ
8091 gen_addr_add(ctx, addr, addr, 2);
8092 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 8093 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 8094#endif
6a6ae23f 8095 tcg_temp_free(t0);
0487d6a8
JM
8096}
8097
636aa200 8098static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8099{
8100 TCGv t0 = tcg_temp_new();
76db3ba4 8101 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8102#if defined(TARGET_PPC64)
8103 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
8104 tcg_gen_shli_tl(t0, t0, 16);
8105 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8106#else
8107 tcg_gen_shli_tl(t0, t0, 16);
8108 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
8109 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
8110#endif
8111 tcg_temp_free(t0);
0487d6a8
JM
8112}
8113
636aa200 8114static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8115{
8116 TCGv t0 = tcg_temp_new();
76db3ba4 8117 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8118#if defined(TARGET_PPC64)
8119 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
8120 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8121#else
8122 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
8123 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
8124#endif
8125 tcg_temp_free(t0);
0487d6a8
JM
8126}
8127
636aa200 8128static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8129{
8130 TCGv t0 = tcg_temp_new();
76db3ba4 8131 gen_qemu_ld16s(ctx, t0, addr);
6a6ae23f
AJ
8132#if defined(TARGET_PPC64)
8133 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
8134 tcg_gen_ext32u_tl(t0, t0);
8135 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8136#else
8137 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
8138 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
8139#endif
8140 tcg_temp_free(t0);
8141}
8142
636aa200 8143static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8144{
8145 TCGv t0 = tcg_temp_new();
8146#if defined(TARGET_PPC64)
76db3ba4 8147 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 8148 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
76db3ba4
AJ
8149 gen_addr_add(ctx, addr, addr, 2);
8150 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8151 tcg_gen_shli_tl(t0, t0, 16);
8152 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8153#else
76db3ba4 8154 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 8155 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
76db3ba4
AJ
8156 gen_addr_add(ctx, addr, addr, 2);
8157 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8158 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
8159#endif
8160 tcg_temp_free(t0);
8161}
8162
636aa200 8163static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8164{
8165#if defined(TARGET_PPC64)
8166 TCGv t0 = tcg_temp_new();
76db3ba4
AJ
8167 gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
8168 gen_addr_add(ctx, addr, addr, 2);
8169 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8170 tcg_gen_shli_tl(t0, t0, 32);
8171 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8172 tcg_temp_free(t0);
8173#else
76db3ba4
AJ
8174 gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
8175 gen_addr_add(ctx, addr, addr, 2);
8176 gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f
AJ
8177#endif
8178}
8179
636aa200 8180static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8181{
8182#if defined(TARGET_PPC64)
8183 TCGv t0 = tcg_temp_new();
76db3ba4 8184 gen_qemu_ld16s(ctx, t0, addr);
6a6ae23f 8185 tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
76db3ba4
AJ
8186 gen_addr_add(ctx, addr, addr, 2);
8187 gen_qemu_ld16s(ctx, t0, addr);
6a6ae23f
AJ
8188 tcg_gen_shli_tl(t0, t0, 32);
8189 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8190 tcg_temp_free(t0);
8191#else
76db3ba4
AJ
8192 gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
8193 gen_addr_add(ctx, addr, addr, 2);
8194 gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f
AJ
8195#endif
8196}
8197
636aa200 8198static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8199{
8200 TCGv t0 = tcg_temp_new();
76db3ba4 8201 gen_qemu_ld32u(ctx, t0, addr);
0487d6a8 8202#if defined(TARGET_PPC64)
6a6ae23f
AJ
8203 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
8204 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8205#else
8206 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
8207 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
8208#endif
8209 tcg_temp_free(t0);
8210}
8211
636aa200 8212static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8213{
8214 TCGv t0 = tcg_temp_new();
8215#if defined(TARGET_PPC64)
76db3ba4 8216 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8217 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
8218 tcg_gen_shli_tl(t0, t0, 32);
8219 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
76db3ba4
AJ
8220 gen_addr_add(ctx, addr, addr, 2);
8221 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8222 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8223 tcg_gen_shli_tl(t0, t0, 16);
8224 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
8225#else
76db3ba4 8226 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8227 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
8228 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
76db3ba4
AJ
8229 gen_addr_add(ctx, addr, addr, 2);
8230 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
8231 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
8232 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
0487d6a8 8233#endif
6a6ae23f
AJ
8234 tcg_temp_free(t0);
8235}
8236
636aa200 8237static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8238{
8239#if defined(TARGET_PPC64)
76db3ba4 8240 gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
0487d6a8 8241#else
6a6ae23f
AJ
8242 TCGv_i64 t0 = tcg_temp_new_i64();
8243 tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
76db3ba4 8244 gen_qemu_st64(ctx, t0, addr);
6a6ae23f
AJ
8245 tcg_temp_free_i64(t0);
8246#endif
8247}
8248
636aa200 8249static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
6a6ae23f 8250{
0487d6a8 8251#if defined(TARGET_PPC64)
6a6ae23f
AJ
8252 TCGv t0 = tcg_temp_new();
8253 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
76db3ba4 8254 gen_qemu_st32(ctx, t0, addr);
6a6ae23f
AJ
8255 tcg_temp_free(t0);
8256#else
76db3ba4 8257 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6a6ae23f 8258#endif
76db3ba4
AJ
8259 gen_addr_add(ctx, addr, addr, 4);
8260 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
8261}
8262
636aa200 8263static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8264{
8265 TCGv t0 = tcg_temp_new();
8266#if defined(TARGET_PPC64)
8267 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
8268#else
8269 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
8270#endif
76db3ba4
AJ
8271 gen_qemu_st16(ctx, t0, addr);
8272 gen_addr_add(ctx, addr, addr, 2);
6a6ae23f
AJ
8273#if defined(TARGET_PPC64)
8274 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
76db3ba4 8275 gen_qemu_st16(ctx, t0, addr);
6a6ae23f 8276#else
76db3ba4 8277 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6a6ae23f 8278#endif
76db3ba4 8279 gen_addr_add(ctx, addr, addr, 2);
6a6ae23f 8280 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
76db3ba4 8281 gen_qemu_st16(ctx, t0, addr);
6a6ae23f 8282 tcg_temp_free(t0);
76db3ba4
AJ
8283 gen_addr_add(ctx, addr, addr, 2);
8284 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
8285}
8286
636aa200 8287static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8288{
8289 TCGv t0 = tcg_temp_new();
8290#if defined(TARGET_PPC64)
8291 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
8292#else
8293 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
8294#endif
76db3ba4
AJ
8295 gen_qemu_st16(ctx, t0, addr);
8296 gen_addr_add(ctx, addr, addr, 2);
6a6ae23f 8297 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
76db3ba4 8298 gen_qemu_st16(ctx, t0, addr);
6a6ae23f
AJ
8299 tcg_temp_free(t0);
8300}
8301
636aa200 8302static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8303{
8304#if defined(TARGET_PPC64)
8305 TCGv t0 = tcg_temp_new();
8306 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
76db3ba4 8307 gen_qemu_st16(ctx, t0, addr);
6a6ae23f
AJ
8308 tcg_temp_free(t0);
8309#else
76db3ba4 8310 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6a6ae23f 8311#endif
76db3ba4
AJ
8312 gen_addr_add(ctx, addr, addr, 2);
8313 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
8314}
8315
636aa200 8316static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
8317{
8318#if defined(TARGET_PPC64)
8319 TCGv t0 = tcg_temp_new();
8320 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
76db3ba4 8321 gen_qemu_st32(ctx, t0, addr);
6a6ae23f
AJ
8322 tcg_temp_free(t0);
8323#else
76db3ba4 8324 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6a6ae23f
AJ
8325#endif
8326}
8327
636aa200 8328static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
6a6ae23f 8329{
76db3ba4 8330 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
8331}
8332
8333#define GEN_SPEOP_LDST(name, opc2, sh) \
99e300ef 8334static void glue(gen_, name)(DisasContext *ctx) \
6a6ae23f
AJ
8335{ \
8336 TCGv t0; \
8337 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8338 gen_exception(ctx, POWERPC_EXCP_SPEU); \
6a6ae23f
AJ
8339 return; \
8340 } \
76db3ba4 8341 gen_set_access_type(ctx, ACCESS_INT); \
6a6ae23f
AJ
8342 t0 = tcg_temp_new(); \
8343 if (Rc(ctx->opcode)) { \
76db3ba4 8344 gen_addr_spe_imm_index(ctx, t0, sh); \
6a6ae23f 8345 } else { \
76db3ba4 8346 gen_addr_reg_index(ctx, t0); \
6a6ae23f
AJ
8347 } \
8348 gen_op_##name(ctx, t0); \
8349 tcg_temp_free(t0); \
8350}
8351
8352GEN_SPEOP_LDST(evldd, 0x00, 3);
8353GEN_SPEOP_LDST(evldw, 0x01, 3);
8354GEN_SPEOP_LDST(evldh, 0x02, 3);
8355GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
8356GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
8357GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
8358GEN_SPEOP_LDST(evlwhe, 0x08, 2);
8359GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
8360GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
8361GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
8362GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
8363
8364GEN_SPEOP_LDST(evstdd, 0x10, 3);
8365GEN_SPEOP_LDST(evstdw, 0x11, 3);
8366GEN_SPEOP_LDST(evstdh, 0x12, 3);
8367GEN_SPEOP_LDST(evstwhe, 0x18, 2);
8368GEN_SPEOP_LDST(evstwho, 0x1A, 2);
8369GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
8370GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
0487d6a8
JM
8371
8372/* Multiply and add - TODO */
8373#if 0
70560da7
FC
8374GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);//
8375GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8376GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE);
8377GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8378GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE);
8379GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8380GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8381GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8382GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE);
8383GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8384GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE);
8385GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8386
8387GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8388GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
8389GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, 0x00000000, PPC_SPE);
8390GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8391GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8392GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8393GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8394GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE);
8395GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, 0x00000000, PPC_SPE);
8396GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8397GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8398GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8399
8400GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
8401GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
8402GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
8403GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, 0x0000F800, PPC_SPE);
8404GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, 0x00000000, PPC_SPE);
8405
8406GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, 0x00000000, PPC_SPE);
8407GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8408GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, 0x00000000, PPC_SPE);
8409GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8410GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, 0x00000000, PPC_SPE);
8411GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8412GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, 0x00000000, PPC_SPE);
8413GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8414GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, 0x00000000, PPC_SPE);
8415GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8416GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, 0x00000000, PPC_SPE);
8417GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8418
8419GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, 0x00000000, PPC_SPE);
8420GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, 0x00000000, PPC_SPE);
8421GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8422GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8423
8424GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, 0x00000000, PPC_SPE);
8425GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8426GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, 0x00000000, PPC_SPE);
8427GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8428GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, 0x00000000, PPC_SPE);
8429GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8430GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, 0x00000000, PPC_SPE);
8431GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8432GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, 0x00000000, PPC_SPE);
8433GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8434GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, 0x00000000, PPC_SPE);
8435GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8436
8437GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, 0x00000000, PPC_SPE);
8438GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, 0x00000000, PPC_SPE);
8439GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
8440GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, 0x00000000, PPC_SPE);
8441GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE);
0487d6a8
JM
8442#endif
8443
8444/*** SPE floating-point extension ***/
1c97856d
AJ
8445#if defined(TARGET_PPC64)
8446#define GEN_SPEFPUOP_CONV_32_32(name) \
636aa200 8447static inline void gen_##name(DisasContext *ctx) \
0487d6a8 8448{ \
1c97856d
AJ
8449 TCGv_i32 t0; \
8450 TCGv t1; \
8451 t0 = tcg_temp_new_i32(); \
8452 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
8e703949 8453 gen_helper_##name(t0, cpu_env, t0); \
1c97856d
AJ
8454 t1 = tcg_temp_new(); \
8455 tcg_gen_extu_i32_tl(t1, t0); \
8456 tcg_temp_free_i32(t0); \
8457 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
8458 0xFFFFFFFF00000000ULL); \
8459 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
8460 tcg_temp_free(t1); \
0487d6a8 8461}
1c97856d 8462#define GEN_SPEFPUOP_CONV_32_64(name) \
636aa200 8463static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8464{ \
8465 TCGv_i32 t0; \
8466 TCGv t1; \
8467 t0 = tcg_temp_new_i32(); \
8e703949 8468 gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]); \
1c97856d
AJ
8469 t1 = tcg_temp_new(); \
8470 tcg_gen_extu_i32_tl(t1, t0); \
8471 tcg_temp_free_i32(t0); \
8472 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
8473 0xFFFFFFFF00000000ULL); \
8474 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
8475 tcg_temp_free(t1); \
8476}
8477#define GEN_SPEFPUOP_CONV_64_32(name) \
636aa200 8478static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8479{ \
8480 TCGv_i32 t0 = tcg_temp_new_i32(); \
8481 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
8e703949 8482 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); \
1c97856d
AJ
8483 tcg_temp_free_i32(t0); \
8484}
8485#define GEN_SPEFPUOP_CONV_64_64(name) \
636aa200 8486static inline void gen_##name(DisasContext *ctx) \
1c97856d 8487{ \
8e703949
BS
8488 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, \
8489 cpu_gpr[rB(ctx->opcode)]); \
1c97856d
AJ
8490}
8491#define GEN_SPEFPUOP_ARITH2_32_32(name) \
636aa200 8492static inline void gen_##name(DisasContext *ctx) \
57951c27 8493{ \
1c97856d
AJ
8494 TCGv_i32 t0, t1; \
8495 TCGv_i64 t2; \
57951c27 8496 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8497 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
8498 return; \
8499 } \
1c97856d
AJ
8500 t0 = tcg_temp_new_i32(); \
8501 t1 = tcg_temp_new_i32(); \
8502 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
8503 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
8e703949 8504 gen_helper_##name(t0, cpu_env, t0, t1); \
1c97856d
AJ
8505 tcg_temp_free_i32(t1); \
8506 t2 = tcg_temp_new(); \
8507 tcg_gen_extu_i32_tl(t2, t0); \
8508 tcg_temp_free_i32(t0); \
8509 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
8510 0xFFFFFFFF00000000ULL); \
8511 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2); \
8512 tcg_temp_free(t2); \
57951c27 8513}
1c97856d 8514#define GEN_SPEFPUOP_ARITH2_64_64(name) \
636aa200 8515static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
8516{ \
8517 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8518 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
8519 return; \
8520 } \
8e703949
BS
8521 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, \
8522 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
57951c27 8523}
1c97856d 8524#define GEN_SPEFPUOP_COMP_32(name) \
636aa200 8525static inline void gen_##name(DisasContext *ctx) \
57951c27 8526{ \
1c97856d 8527 TCGv_i32 t0, t1; \
57951c27 8528 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8529 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
8530 return; \
8531 } \
1c97856d
AJ
8532 t0 = tcg_temp_new_i32(); \
8533 t1 = tcg_temp_new_i32(); \
8534 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
8535 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
8e703949 8536 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
1c97856d
AJ
8537 tcg_temp_free_i32(t0); \
8538 tcg_temp_free_i32(t1); \
8539}
8540#define GEN_SPEFPUOP_COMP_64(name) \
636aa200 8541static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8542{ \
8543 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8544 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
8545 return; \
8546 } \
8e703949 8547 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, \
1c97856d
AJ
8548 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8549}
8550#else
8551#define GEN_SPEFPUOP_CONV_32_32(name) \
636aa200 8552static inline void gen_##name(DisasContext *ctx) \
1c97856d 8553{ \
8e703949
BS
8554 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, \
8555 cpu_gpr[rB(ctx->opcode)]); \
57951c27 8556}
1c97856d 8557#define GEN_SPEFPUOP_CONV_32_64(name) \
636aa200 8558static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8559{ \
8560 TCGv_i64 t0 = tcg_temp_new_i64(); \
8561 gen_load_gpr64(t0, rB(ctx->opcode)); \
8e703949 8562 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); \
1c97856d
AJ
8563 tcg_temp_free_i64(t0); \
8564}
8565#define GEN_SPEFPUOP_CONV_64_32(name) \
636aa200 8566static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8567{ \
8568 TCGv_i64 t0 = tcg_temp_new_i64(); \
8e703949 8569 gen_helper_##name(t0, cpu_env, cpu_gpr[rB(ctx->opcode)]); \
1c97856d
AJ
8570 gen_store_gpr64(rD(ctx->opcode), t0); \
8571 tcg_temp_free_i64(t0); \
8572}
8573#define GEN_SPEFPUOP_CONV_64_64(name) \
636aa200 8574static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8575{ \
8576 TCGv_i64 t0 = tcg_temp_new_i64(); \
8577 gen_load_gpr64(t0, rB(ctx->opcode)); \
8e703949 8578 gen_helper_##name(t0, cpu_env, t0); \
1c97856d
AJ
8579 gen_store_gpr64(rD(ctx->opcode), t0); \
8580 tcg_temp_free_i64(t0); \
8581}
8582#define GEN_SPEFPUOP_ARITH2_32_32(name) \
636aa200 8583static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8584{ \
8585 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8586 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
8587 return; \
8588 } \
8e703949 8589 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_env, \
1c97856d
AJ
8590 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8591}
8592#define GEN_SPEFPUOP_ARITH2_64_64(name) \
636aa200 8593static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8594{ \
8595 TCGv_i64 t0, t1; \
8596 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8597 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
8598 return; \
8599 } \
8600 t0 = tcg_temp_new_i64(); \
8601 t1 = tcg_temp_new_i64(); \
8602 gen_load_gpr64(t0, rA(ctx->opcode)); \
8603 gen_load_gpr64(t1, rB(ctx->opcode)); \
8e703949 8604 gen_helper_##name(t0, cpu_env, t0, t1); \
1c97856d
AJ
8605 gen_store_gpr64(rD(ctx->opcode), t0); \
8606 tcg_temp_free_i64(t0); \
8607 tcg_temp_free_i64(t1); \
8608}
8609#define GEN_SPEFPUOP_COMP_32(name) \
636aa200 8610static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8611{ \
8612 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8613 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
8614 return; \
8615 } \
8e703949 8616 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, \
1c97856d
AJ
8617 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8618}
8619#define GEN_SPEFPUOP_COMP_64(name) \
636aa200 8620static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8621{ \
8622 TCGv_i64 t0, t1; \
8623 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8624 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
8625 return; \
8626 } \
8627 t0 = tcg_temp_new_i64(); \
8628 t1 = tcg_temp_new_i64(); \
8629 gen_load_gpr64(t0, rA(ctx->opcode)); \
8630 gen_load_gpr64(t1, rB(ctx->opcode)); \
8e703949 8631 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
1c97856d
AJ
8632 tcg_temp_free_i64(t0); \
8633 tcg_temp_free_i64(t1); \
8634}
8635#endif
57951c27 8636
0487d6a8
JM
8637/* Single precision floating-point vectors operations */
8638/* Arithmetic */
1c97856d
AJ
8639GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
8640GEN_SPEFPUOP_ARITH2_64_64(evfssub);
8641GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
8642GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
636aa200 8643static inline void gen_evfsabs(DisasContext *ctx)
1c97856d
AJ
8644{
8645 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8646 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8647 return;
8648 }
8649#if defined(TARGET_PPC64)
6d5c34fa 8650 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
1c97856d 8651#else
6d5c34fa
MP
8652 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
8653 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
1c97856d
AJ
8654#endif
8655}
636aa200 8656static inline void gen_evfsnabs(DisasContext *ctx)
1c97856d
AJ
8657{
8658 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8659 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8660 return;
8661 }
8662#if defined(TARGET_PPC64)
6d5c34fa 8663 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
1c97856d 8664#else
6d5c34fa
MP
8665 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
8666 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8667#endif
8668}
636aa200 8669static inline void gen_evfsneg(DisasContext *ctx)
1c97856d
AJ
8670{
8671 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8672 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8673 return;
8674 }
8675#if defined(TARGET_PPC64)
6d5c34fa 8676 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
1c97856d 8677#else
6d5c34fa
MP
8678 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
8679 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8680#endif
8681}
8682
0487d6a8 8683/* Conversion */
1c97856d
AJ
8684GEN_SPEFPUOP_CONV_64_64(evfscfui);
8685GEN_SPEFPUOP_CONV_64_64(evfscfsi);
8686GEN_SPEFPUOP_CONV_64_64(evfscfuf);
8687GEN_SPEFPUOP_CONV_64_64(evfscfsf);
8688GEN_SPEFPUOP_CONV_64_64(evfsctui);
8689GEN_SPEFPUOP_CONV_64_64(evfsctsi);
8690GEN_SPEFPUOP_CONV_64_64(evfsctuf);
8691GEN_SPEFPUOP_CONV_64_64(evfsctsf);
8692GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
8693GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
8694
0487d6a8 8695/* Comparison */
1c97856d
AJ
8696GEN_SPEFPUOP_COMP_64(evfscmpgt);
8697GEN_SPEFPUOP_COMP_64(evfscmplt);
8698GEN_SPEFPUOP_COMP_64(evfscmpeq);
8699GEN_SPEFPUOP_COMP_64(evfststgt);
8700GEN_SPEFPUOP_COMP_64(evfststlt);
8701GEN_SPEFPUOP_COMP_64(evfststeq);
0487d6a8
JM
8702
8703/* Opcodes definitions */
70560da7
FC
8704GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
8705GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
8706GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8707GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
8708GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
8709GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8710GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8711GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8712GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8713GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8714GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8715GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8716GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
8717GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
0487d6a8
JM
8718
8719/* Single precision floating-point operations */
8720/* Arithmetic */
1c97856d
AJ
8721GEN_SPEFPUOP_ARITH2_32_32(efsadd);
8722GEN_SPEFPUOP_ARITH2_32_32(efssub);
8723GEN_SPEFPUOP_ARITH2_32_32(efsmul);
8724GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
636aa200 8725static inline void gen_efsabs(DisasContext *ctx)
1c97856d
AJ
8726{
8727 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8728 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8729 return;
8730 }
6d5c34fa 8731 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
1c97856d 8732}
636aa200 8733static inline void gen_efsnabs(DisasContext *ctx)
1c97856d
AJ
8734{
8735 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8736 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8737 return;
8738 }
6d5c34fa 8739 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1c97856d 8740}
636aa200 8741static inline void gen_efsneg(DisasContext *ctx)
1c97856d
AJ
8742{
8743 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8744 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8745 return;
8746 }
6d5c34fa 8747 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8748}
8749
0487d6a8 8750/* Conversion */
1c97856d
AJ
8751GEN_SPEFPUOP_CONV_32_32(efscfui);
8752GEN_SPEFPUOP_CONV_32_32(efscfsi);
8753GEN_SPEFPUOP_CONV_32_32(efscfuf);
8754GEN_SPEFPUOP_CONV_32_32(efscfsf);
8755GEN_SPEFPUOP_CONV_32_32(efsctui);
8756GEN_SPEFPUOP_CONV_32_32(efsctsi);
8757GEN_SPEFPUOP_CONV_32_32(efsctuf);
8758GEN_SPEFPUOP_CONV_32_32(efsctsf);
8759GEN_SPEFPUOP_CONV_32_32(efsctuiz);
8760GEN_SPEFPUOP_CONV_32_32(efsctsiz);
8761GEN_SPEFPUOP_CONV_32_64(efscfd);
8762
0487d6a8 8763/* Comparison */
1c97856d
AJ
8764GEN_SPEFPUOP_COMP_32(efscmpgt);
8765GEN_SPEFPUOP_COMP_32(efscmplt);
8766GEN_SPEFPUOP_COMP_32(efscmpeq);
8767GEN_SPEFPUOP_COMP_32(efststgt);
8768GEN_SPEFPUOP_COMP_32(efststlt);
8769GEN_SPEFPUOP_COMP_32(efststeq);
0487d6a8
JM
8770
8771/* Opcodes definitions */
70560da7
FC
8772GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
8773GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); //
8774GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8775GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); //
8776GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
8777GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE); //
8778GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8779GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8780GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8781GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); //
8782GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8783GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
8784GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); //
8785GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); //
0487d6a8
JM
8786
8787/* Double precision floating-point operations */
8788/* Arithmetic */
1c97856d
AJ
8789GEN_SPEFPUOP_ARITH2_64_64(efdadd);
8790GEN_SPEFPUOP_ARITH2_64_64(efdsub);
8791GEN_SPEFPUOP_ARITH2_64_64(efdmul);
8792GEN_SPEFPUOP_ARITH2_64_64(efddiv);
636aa200 8793static inline void gen_efdabs(DisasContext *ctx)
1c97856d
AJ
8794{
8795 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8796 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8797 return;
8798 }
8799#if defined(TARGET_PPC64)
6d5c34fa 8800 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
1c97856d 8801#else
6d5c34fa
MP
8802 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8803 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
1c97856d
AJ
8804#endif
8805}
636aa200 8806static inline void gen_efdnabs(DisasContext *ctx)
1c97856d
AJ
8807{
8808 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8809 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8810 return;
8811 }
8812#if defined(TARGET_PPC64)
6d5c34fa 8813 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
1c97856d 8814#else
6d5c34fa
MP
8815 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8816 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8817#endif
8818}
636aa200 8819static inline void gen_efdneg(DisasContext *ctx)
1c97856d
AJ
8820{
8821 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8822 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8823 return;
8824 }
8825#if defined(TARGET_PPC64)
6d5c34fa 8826 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
1c97856d 8827#else
6d5c34fa
MP
8828 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8829 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8830#endif
8831}
8832
0487d6a8 8833/* Conversion */
1c97856d
AJ
8834GEN_SPEFPUOP_CONV_64_32(efdcfui);
8835GEN_SPEFPUOP_CONV_64_32(efdcfsi);
8836GEN_SPEFPUOP_CONV_64_32(efdcfuf);
8837GEN_SPEFPUOP_CONV_64_32(efdcfsf);
8838GEN_SPEFPUOP_CONV_32_64(efdctui);
8839GEN_SPEFPUOP_CONV_32_64(efdctsi);
8840GEN_SPEFPUOP_CONV_32_64(efdctuf);
8841GEN_SPEFPUOP_CONV_32_64(efdctsf);
8842GEN_SPEFPUOP_CONV_32_64(efdctuiz);
8843GEN_SPEFPUOP_CONV_32_64(efdctsiz);
8844GEN_SPEFPUOP_CONV_64_32(efdcfs);
8845GEN_SPEFPUOP_CONV_64_64(efdcfuid);
8846GEN_SPEFPUOP_CONV_64_64(efdcfsid);
8847GEN_SPEFPUOP_CONV_64_64(efdctuidz);
8848GEN_SPEFPUOP_CONV_64_64(efdctsidz);
0487d6a8 8849
0487d6a8 8850/* Comparison */
1c97856d
AJ
8851GEN_SPEFPUOP_COMP_64(efdcmpgt);
8852GEN_SPEFPUOP_COMP_64(efdcmplt);
8853GEN_SPEFPUOP_COMP_64(efdcmpeq);
8854GEN_SPEFPUOP_COMP_64(efdtstgt);
8855GEN_SPEFPUOP_COMP_64(efdtstlt);
8856GEN_SPEFPUOP_COMP_64(efdtsteq);
0487d6a8
JM
8857
8858/* Opcodes definitions */
70560da7
FC
8859GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
8860GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8861GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE); //
8862GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
8863GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); //
8864GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8865GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
8866GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE); //
8867GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8868GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8869GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8870GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); //
8871GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
8872GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
8873GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
8874GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
0487d6a8 8875
c227f099 8876static opcode_t opcodes[] = {
5c55ff99
BS
8877GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
8878GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
8879GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
8880GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
8881GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
fcfda20f 8882GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
5c55ff99
BS
8883GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
8884GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8885GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8886GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8887GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8888GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
8889GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
8890GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
8891GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
8892GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8893#if defined(TARGET_PPC64)
8894GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
8895#endif
8896GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
8897GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
8898GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8899GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8900GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8901GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
8902GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
8903GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
8904GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8905GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8906GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8907GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8908GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
eaabeef2 8909GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
725bcec2 8910GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
5c55ff99 8911#if defined(TARGET_PPC64)
eaabeef2 8912GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
5c55ff99 8913GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
725bcec2 8914GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
5c55ff99
BS
8915#endif
8916GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8917GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8918GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8919GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
8920GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
8921GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
8922GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
8923#if defined(TARGET_PPC64)
8924GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
8925GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
8926GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
8927GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
8928GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
8929#endif
8930GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
8931GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8932GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8933GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
8934GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
bf45a2e6 8935GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT),
5c55ff99 8936GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
bf45a2e6
AJ
8937GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT),
8938GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT),
f0332888 8939GEN_HANDLER_E(fcpsgn, 0x3F, 0x08, 0x00, 0x00000000, PPC_NONE, PPC2_ISA205),
5c55ff99
BS
8940GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
8941GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
8942GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
8943GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
7d08d856
AJ
8944GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00000000, PPC_FLOAT),
8945GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006e0800, PPC_FLOAT),
5c55ff99
BS
8946#if defined(TARGET_PPC64)
8947GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
8948GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
8949GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
8950#endif
8951GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8952GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8953GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
8954GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
8955GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
8956GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
8957GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
8958GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
f844c817 8959GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
5c55ff99
BS
8960GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
8961#if defined(TARGET_PPC64)
f844c817 8962GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
5c55ff99
BS
8963GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
8964#endif
8965GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
8966GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
8967GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8968GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8969GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
8970GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
8971GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
8972GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
8973#if defined(TARGET_PPC64)
8974GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
8975GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
8976#endif
8977GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
8978GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
8979GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8980#if defined(TARGET_PPC64)
8981GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
8982GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
8983#endif
8984GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
8985GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
8986GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
8987GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
8988GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
8989GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
8990#if defined(TARGET_PPC64)
8991GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
8992#endif
8993GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC),
8994GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC),
8995GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
8996GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
8997GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
8998GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE),
8999GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE),
8e33944f 9000GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
5c55ff99
BS
9001GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
9002GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
9003GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
9004GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
9005GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
9006GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
9007GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
9008GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
9009GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
9010#if defined(TARGET_PPC64)
9011GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
9012GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
9013 PPC_SEGMENT_64B),
9014GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
9015GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
9016 PPC_SEGMENT_64B),
efdef95f
DG
9017GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
9018GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
9019GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
5c55ff99
BS
9020#endif
9021GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
9022GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
9023GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE),
9024GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
9025#if defined(TARGET_PPC64)
9026GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
9027GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
9028#endif
9029GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
9030GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
9031GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
9032GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
9033GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
9034GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
9035GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
9036GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
9037GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
9038GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
9039GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
9040GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
9041GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
9042GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
9043GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
9044GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
9045GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
9046GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
9047GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
9048GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
9049GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
9050GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
9051GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
9052GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
9053GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
9054GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
9055GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
9056GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
9057GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
9058GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
9059GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
9060GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
9061GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
9062GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
9063GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
9064GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
9065GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
9066GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
9067GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
9068GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
9069GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
9070GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
9071GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
9072GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
9073GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
9074GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
9075GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
9076GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
9077GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
9078GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
9079GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
9080GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
9081GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
9082GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
9083GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
9084GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
9085GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
9086GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
9087GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
9088GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
9089GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
9090GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
9091GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
9092GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
9093GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
9094GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
9095GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
9096GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
9097GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
9098GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
9099GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
01662f3e 9100GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
5c55ff99
BS
9101GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
9102GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
9103GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
9104GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
9105GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
9106GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
9107GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
9108GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
01662f3e
AG
9109GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
9110 PPC_NONE, PPC2_BOOKE206),
9111GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
9112 PPC_NONE, PPC2_BOOKE206),
9113GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
9114 PPC_NONE, PPC2_BOOKE206),
9115GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
9116 PPC_NONE, PPC2_BOOKE206),
6d3db821
AG
9117GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
9118 PPC_NONE, PPC2_BOOKE206),
d5d11a39
AG
9119GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
9120 PPC_NONE, PPC2_PRCNTL),
9e0b5cb1
AG
9121GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
9122 PPC_NONE, PPC2_PRCNTL),
5c55ff99 9123GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
fbe73008 9124GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
5c55ff99 9125GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
01662f3e
AG
9126GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
9127 PPC_BOOKE, PPC2_BOOKE206),
dcb2b9e1 9128GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
01662f3e
AG
9129GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
9130 PPC_BOOKE, PPC2_BOOKE206),
5c55ff99
BS
9131GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
9132GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
9133GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
9134GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
9135GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC),
9136GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
9137GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
9138GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
9139GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
9140GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),
9141
9142#undef GEN_INT_ARITH_ADD
9143#undef GEN_INT_ARITH_ADD_CONST
9144#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
9145GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
9146#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
9147 add_ca, compute_ca, compute_ov) \
9148GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
9149GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
9150GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
9151GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
9152GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
9153GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
9154GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
9155GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
9156GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
9157GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
9158GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
9159
9160#undef GEN_INT_ARITH_DIVW
9161#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
9162GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
9163GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
9164GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
9165GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
9166GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
9167
9168#if defined(TARGET_PPC64)
9169#undef GEN_INT_ARITH_DIVD
9170#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
9171GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
9172GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
9173GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
9174GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
9175GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
9176
9177#undef GEN_INT_ARITH_MUL_HELPER
9178#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
9179GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
9180GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
9181GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
9182GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
9183#endif
9184
9185#undef GEN_INT_ARITH_SUBF
9186#undef GEN_INT_ARITH_SUBF_CONST
9187#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
9188GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
9189#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
9190 add_ca, compute_ca, compute_ov) \
9191GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
9192GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
9193GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
9194GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
9195GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
9196GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
9197GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
9198GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
9199GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
9200GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
9201GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
9202
9203#undef GEN_LOGICAL1
9204#undef GEN_LOGICAL2
9205#define GEN_LOGICAL2(name, tcg_op, opc, type) \
9206GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
9207#define GEN_LOGICAL1(name, tcg_op, opc, type) \
9208GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
9209GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
9210GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
9211GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
9212GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
9213GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
9214GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
9215GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
9216GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
9217#if defined(TARGET_PPC64)
9218GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
9219#endif
9220
9221#if defined(TARGET_PPC64)
9222#undef GEN_PPC64_R2
9223#undef GEN_PPC64_R4
9224#define GEN_PPC64_R2(name, opc1, opc2) \
9225GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
9226GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
9227 PPC_64B)
9228#define GEN_PPC64_R4(name, opc1, opc2) \
9229GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
9230GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
9231 PPC_64B), \
9232GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
9233 PPC_64B), \
9234GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
9235 PPC_64B)
9236GEN_PPC64_R4(rldicl, 0x1E, 0x00),
9237GEN_PPC64_R4(rldicr, 0x1E, 0x02),
9238GEN_PPC64_R4(rldic, 0x1E, 0x04),
9239GEN_PPC64_R2(rldcl, 0x1E, 0x08),
9240GEN_PPC64_R2(rldcr, 0x1E, 0x09),
9241GEN_PPC64_R4(rldimi, 0x1E, 0x06),
9242#endif
9243
9244#undef _GEN_FLOAT_ACB
9245#undef GEN_FLOAT_ACB
9246#undef _GEN_FLOAT_AB
9247#undef GEN_FLOAT_AB
9248#undef _GEN_FLOAT_AC
9249#undef GEN_FLOAT_AC
9250#undef GEN_FLOAT_B
9251#undef GEN_FLOAT_BS
9252#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
9253GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
9254#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
9255_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type), \
9256_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type)
9257#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
9258GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
9259#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
9260_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
9261_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
9262#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
9263GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
9264#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
9265_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
9266_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
9267#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
9268GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
9269#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
9270GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)
9271
9272GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
9273GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
9274GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
9275GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
9276GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
9277GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
9278_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
9279GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
9280GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
9281GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
9282GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
9283GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
9284GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
9285GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
9286GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
9287#if defined(TARGET_PPC64)
9288GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B),
9289GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B),
9290GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B),
9291#endif
9292GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
9293GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
9294GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
9295GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
5c55ff99
BS
9296
9297#undef GEN_LD
9298#undef GEN_LDU
9299#undef GEN_LDUX
cd6e9320 9300#undef GEN_LDX_E
5c55ff99
BS
9301#undef GEN_LDS
9302#define GEN_LD(name, ldop, opc, type) \
9303GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
9304#define GEN_LDU(name, ldop, opc, type) \
9305GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
9306#define GEN_LDUX(name, ldop, opc2, opc3, type) \
9307GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
cd6e9320
TH
9308#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
9309GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
5c55ff99
BS
9310#define GEN_LDS(name, ldop, op, type) \
9311GEN_LD(name, ldop, op | 0x20, type) \
9312GEN_LDU(name, ldop, op | 0x21, type) \
9313GEN_LDUX(name, ldop, 0x17, op | 0x01, type) \
9314GEN_LDX(name, ldop, 0x17, op | 0x00, type)
9315
9316GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
9317GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
9318GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
9319GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
9320#if defined(TARGET_PPC64)
9321GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
9322GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
9323GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
9324GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
cd6e9320 9325GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
5c55ff99
BS
9326#endif
9327GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
9328GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
9329
9330#undef GEN_ST
9331#undef GEN_STU
9332#undef GEN_STUX
cd6e9320 9333#undef GEN_STX_E
5c55ff99
BS
9334#undef GEN_STS
9335#define GEN_ST(name, stop, opc, type) \
9336GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
9337#define GEN_STU(name, stop, opc, type) \
9338GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
9339#define GEN_STUX(name, stop, opc2, opc3, type) \
9340GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
cd6e9320
TH
9341#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
9342GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
5c55ff99
BS
9343#define GEN_STS(name, stop, op, type) \
9344GEN_ST(name, stop, op | 0x20, type) \
9345GEN_STU(name, stop, op | 0x21, type) \
9346GEN_STUX(name, stop, 0x17, op | 0x01, type) \
9347GEN_STX(name, stop, 0x17, op | 0x00, type)
9348
9349GEN_STS(stb, st8, 0x06, PPC_INTEGER)
9350GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
9351GEN_STS(stw, st32, 0x04, PPC_INTEGER)
9352#if defined(TARGET_PPC64)
9353GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
9354GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
cd6e9320 9355GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
5c55ff99
BS
9356#endif
9357GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
9358GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
9359
9360#undef GEN_LDF
9361#undef GEN_LDUF
9362#undef GEN_LDUXF
9363#undef GEN_LDXF
9364#undef GEN_LDFS
9365#define GEN_LDF(name, ldop, opc, type) \
9366GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
9367#define GEN_LDUF(name, ldop, opc, type) \
9368GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
9369#define GEN_LDUXF(name, ldop, opc, type) \
9370GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
9371#define GEN_LDXF(name, ldop, opc2, opc3, type) \
9372GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
9373#define GEN_LDFS(name, ldop, op, type) \
9374GEN_LDF(name, ldop, op | 0x20, type) \
9375GEN_LDUF(name, ldop, op | 0x21, type) \
9376GEN_LDUXF(name, ldop, op | 0x01, type) \
9377GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
9378
9379GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
9380GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
199f830d 9381GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
05050ee8
AJ
9382GEN_HANDLER_E(lfdp, 0x39, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
9383GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205),
5c55ff99
BS
9384
9385#undef GEN_STF
9386#undef GEN_STUF
9387#undef GEN_STUXF
9388#undef GEN_STXF
9389#undef GEN_STFS
9390#define GEN_STF(name, stop, opc, type) \
9391GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
9392#define GEN_STUF(name, stop, opc, type) \
9393GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
9394#define GEN_STUXF(name, stop, opc, type) \
9395GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
9396#define GEN_STXF(name, stop, opc2, opc3, type) \
9397GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
9398#define GEN_STFS(name, stop, op, type) \
9399GEN_STF(name, stop, op | 0x20, type) \
9400GEN_STUF(name, stop, op | 0x21, type) \
9401GEN_STUXF(name, stop, op | 0x01, type) \
9402GEN_STXF(name, stop, 0x17, op | 0x00, type)
9403
9404GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
9405GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
9406GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
44bc0c4d
AJ
9407GEN_HANDLER_E(stfdp, 0x3D, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
9408GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205),
5c55ff99
BS
9409
9410#undef GEN_CRLOGIC
9411#define GEN_CRLOGIC(name, tcg_op, opc) \
9412GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
9413GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
9414GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
9415GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
9416GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
9417GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
9418GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
9419GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
9420GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
9421
9422#undef GEN_MAC_HANDLER
9423#define GEN_MAC_HANDLER(name, opc2, opc3) \
9424GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
9425GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
9426GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
9427GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
9428GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
9429GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
9430GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
9431GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
9432GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
9433GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
9434GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
9435GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
9436GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
9437GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
9438GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
9439GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
9440GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
9441GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
9442GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
9443GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
9444GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
9445GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
9446GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
9447GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
9448GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
9449GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
9450GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
9451GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
9452GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
9453GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
9454GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
9455GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
9456GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
9457GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
9458GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
9459GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
9460GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
9461GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
9462GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
9463GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
9464GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
9465GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
9466GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
9467
9468#undef GEN_VR_LDX
9469#undef GEN_VR_STX
9470#undef GEN_VR_LVE
9471#undef GEN_VR_STVE
9472#define GEN_VR_LDX(name, opc2, opc3) \
9473GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
9474#define GEN_VR_STX(name, opc2, opc3) \
9475GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
9476#define GEN_VR_LVE(name, opc2, opc3) \
9477 GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
9478#define GEN_VR_STVE(name, opc2, opc3) \
9479 GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
9480GEN_VR_LDX(lvx, 0x07, 0x03),
9481GEN_VR_LDX(lvxl, 0x07, 0x0B),
9482GEN_VR_LVE(bx, 0x07, 0x00),
9483GEN_VR_LVE(hx, 0x07, 0x01),
9484GEN_VR_LVE(wx, 0x07, 0x02),
9485GEN_VR_STX(svx, 0x07, 0x07),
9486GEN_VR_STX(svxl, 0x07, 0x0F),
9487GEN_VR_STVE(bx, 0x07, 0x04),
9488GEN_VR_STVE(hx, 0x07, 0x05),
9489GEN_VR_STVE(wx, 0x07, 0x06),
9490
9491#undef GEN_VX_LOGICAL
9492#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
9493GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9494GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
9495GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
9496GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
9497GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
9498GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),
9499
9500#undef GEN_VXFORM
9501#define GEN_VXFORM(name, opc2, opc3) \
9502GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9503GEN_VXFORM(vaddubm, 0, 0),
9504GEN_VXFORM(vadduhm, 0, 1),
9505GEN_VXFORM(vadduwm, 0, 2),
9506GEN_VXFORM(vsububm, 0, 16),
9507GEN_VXFORM(vsubuhm, 0, 17),
9508GEN_VXFORM(vsubuwm, 0, 18),
9509GEN_VXFORM(vmaxub, 1, 0),
9510GEN_VXFORM(vmaxuh, 1, 1),
9511GEN_VXFORM(vmaxuw, 1, 2),
9512GEN_VXFORM(vmaxsb, 1, 4),
9513GEN_VXFORM(vmaxsh, 1, 5),
9514GEN_VXFORM(vmaxsw, 1, 6),
9515GEN_VXFORM(vminub, 1, 8),
9516GEN_VXFORM(vminuh, 1, 9),
9517GEN_VXFORM(vminuw, 1, 10),
9518GEN_VXFORM(vminsb, 1, 12),
9519GEN_VXFORM(vminsh, 1, 13),
9520GEN_VXFORM(vminsw, 1, 14),
9521GEN_VXFORM(vavgub, 1, 16),
9522GEN_VXFORM(vavguh, 1, 17),
9523GEN_VXFORM(vavguw, 1, 18),
9524GEN_VXFORM(vavgsb, 1, 20),
9525GEN_VXFORM(vavgsh, 1, 21),
9526GEN_VXFORM(vavgsw, 1, 22),
9527GEN_VXFORM(vmrghb, 6, 0),
9528GEN_VXFORM(vmrghh, 6, 1),
9529GEN_VXFORM(vmrghw, 6, 2),
9530GEN_VXFORM(vmrglb, 6, 4),
9531GEN_VXFORM(vmrglh, 6, 5),
9532GEN_VXFORM(vmrglw, 6, 6),
9533GEN_VXFORM(vmuloub, 4, 0),
9534GEN_VXFORM(vmulouh, 4, 1),
9535GEN_VXFORM(vmulosb, 4, 4),
9536GEN_VXFORM(vmulosh, 4, 5),
9537GEN_VXFORM(vmuleub, 4, 8),
9538GEN_VXFORM(vmuleuh, 4, 9),
9539GEN_VXFORM(vmulesb, 4, 12),
9540GEN_VXFORM(vmulesh, 4, 13),
9541GEN_VXFORM(vslb, 2, 4),
9542GEN_VXFORM(vslh, 2, 5),
9543GEN_VXFORM(vslw, 2, 6),
9544GEN_VXFORM(vsrb, 2, 8),
9545GEN_VXFORM(vsrh, 2, 9),
9546GEN_VXFORM(vsrw, 2, 10),
9547GEN_VXFORM(vsrab, 2, 12),
9548GEN_VXFORM(vsrah, 2, 13),
9549GEN_VXFORM(vsraw, 2, 14),
9550GEN_VXFORM(vslo, 6, 16),
9551GEN_VXFORM(vsro, 6, 17),
9552GEN_VXFORM(vaddcuw, 0, 6),
9553GEN_VXFORM(vsubcuw, 0, 22),
9554GEN_VXFORM(vaddubs, 0, 8),
9555GEN_VXFORM(vadduhs, 0, 9),
9556GEN_VXFORM(vadduws, 0, 10),
9557GEN_VXFORM(vaddsbs, 0, 12),
9558GEN_VXFORM(vaddshs, 0, 13),
9559GEN_VXFORM(vaddsws, 0, 14),
9560GEN_VXFORM(vsububs, 0, 24),
9561GEN_VXFORM(vsubuhs, 0, 25),
9562GEN_VXFORM(vsubuws, 0, 26),
9563GEN_VXFORM(vsubsbs, 0, 28),
9564GEN_VXFORM(vsubshs, 0, 29),
9565GEN_VXFORM(vsubsws, 0, 30),
9566GEN_VXFORM(vrlb, 2, 0),
9567GEN_VXFORM(vrlh, 2, 1),
9568GEN_VXFORM(vrlw, 2, 2),
9569GEN_VXFORM(vsl, 2, 7),
9570GEN_VXFORM(vsr, 2, 11),
9571GEN_VXFORM(vpkuhum, 7, 0),
9572GEN_VXFORM(vpkuwum, 7, 1),
9573GEN_VXFORM(vpkuhus, 7, 2),
9574GEN_VXFORM(vpkuwus, 7, 3),
9575GEN_VXFORM(vpkshus, 7, 4),
9576GEN_VXFORM(vpkswus, 7, 5),
9577GEN_VXFORM(vpkshss, 7, 6),
9578GEN_VXFORM(vpkswss, 7, 7),
9579GEN_VXFORM(vpkpx, 7, 12),
9580GEN_VXFORM(vsum4ubs, 4, 24),
9581GEN_VXFORM(vsum4sbs, 4, 28),
9582GEN_VXFORM(vsum4shs, 4, 25),
9583GEN_VXFORM(vsum2sws, 4, 26),
9584GEN_VXFORM(vsumsws, 4, 30),
9585GEN_VXFORM(vaddfp, 5, 0),
9586GEN_VXFORM(vsubfp, 5, 1),
9587GEN_VXFORM(vmaxfp, 5, 16),
9588GEN_VXFORM(vminfp, 5, 17),
9589
9590#undef GEN_VXRFORM1
9591#undef GEN_VXRFORM
9592#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
9593 GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
9594#define GEN_VXRFORM(name, opc2, opc3) \
9595 GEN_VXRFORM1(name, name, #name, opc2, opc3) \
9596 GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
9597GEN_VXRFORM(vcmpequb, 3, 0)
9598GEN_VXRFORM(vcmpequh, 3, 1)
9599GEN_VXRFORM(vcmpequw, 3, 2)
9600GEN_VXRFORM(vcmpgtsb, 3, 12)
9601GEN_VXRFORM(vcmpgtsh, 3, 13)
9602GEN_VXRFORM(vcmpgtsw, 3, 14)
9603GEN_VXRFORM(vcmpgtub, 3, 8)
9604GEN_VXRFORM(vcmpgtuh, 3, 9)
9605GEN_VXRFORM(vcmpgtuw, 3, 10)
9606GEN_VXRFORM(vcmpeqfp, 3, 3)
9607GEN_VXRFORM(vcmpgefp, 3, 7)
9608GEN_VXRFORM(vcmpgtfp, 3, 11)
9609GEN_VXRFORM(vcmpbfp, 3, 15)
9610
9611#undef GEN_VXFORM_SIMM
9612#define GEN_VXFORM_SIMM(name, opc2, opc3) \
9613 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9614GEN_VXFORM_SIMM(vspltisb, 6, 12),
9615GEN_VXFORM_SIMM(vspltish, 6, 13),
9616GEN_VXFORM_SIMM(vspltisw, 6, 14),
9617
9618#undef GEN_VXFORM_NOA
9619#define GEN_VXFORM_NOA(name, opc2, opc3) \
9620 GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
9621GEN_VXFORM_NOA(vupkhsb, 7, 8),
9622GEN_VXFORM_NOA(vupkhsh, 7, 9),
9623GEN_VXFORM_NOA(vupklsb, 7, 10),
9624GEN_VXFORM_NOA(vupklsh, 7, 11),
9625GEN_VXFORM_NOA(vupkhpx, 7, 13),
9626GEN_VXFORM_NOA(vupklpx, 7, 15),
9627GEN_VXFORM_NOA(vrefp, 5, 4),
9628GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
0bffbc6c 9629GEN_VXFORM_NOA(vexptefp, 5, 6),
5c55ff99
BS
9630GEN_VXFORM_NOA(vlogefp, 5, 7),
9631GEN_VXFORM_NOA(vrfim, 5, 8),
9632GEN_VXFORM_NOA(vrfin, 5, 9),
9633GEN_VXFORM_NOA(vrfip, 5, 10),
9634GEN_VXFORM_NOA(vrfiz, 5, 11),
9635
9636#undef GEN_VXFORM_UIMM
9637#define GEN_VXFORM_UIMM(name, opc2, opc3) \
9638 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9639GEN_VXFORM_UIMM(vspltb, 6, 8),
9640GEN_VXFORM_UIMM(vsplth, 6, 9),
9641GEN_VXFORM_UIMM(vspltw, 6, 10),
9642GEN_VXFORM_UIMM(vcfux, 5, 12),
9643GEN_VXFORM_UIMM(vcfsx, 5, 13),
9644GEN_VXFORM_UIMM(vctuxs, 5, 14),
9645GEN_VXFORM_UIMM(vctsxs, 5, 15),
9646
9647#undef GEN_VAFORM_PAIRED
9648#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
9649 GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
9650GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
9651GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
9652GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
9653GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
9654GEN_VAFORM_PAIRED(vsel, vperm, 21),
9655GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
9656
fa1832d7 9657GEN_HANDLER_E(lxsdx, 0x1F, 0x0C, 0x12, 0, PPC_NONE, PPC2_VSX),
304af367 9658GEN_HANDLER_E(lxvd2x, 0x1F, 0x0C, 0x1A, 0, PPC_NONE, PPC2_VSX),
ca03b467 9659GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX),
897e61d1 9660GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX),
304af367 9661
9231ba9e 9662GEN_HANDLER_E(stxsdx, 0x1F, 0xC, 0x16, 0, PPC_NONE, PPC2_VSX),
fbed2478 9663GEN_HANDLER_E(stxvd2x, 0x1F, 0xC, 0x1E, 0, PPC_NONE, PPC2_VSX),
86e61ce3 9664GEN_HANDLER_E(stxvw4x, 0x1F, 0xC, 0x1C, 0, PPC_NONE, PPC2_VSX),
fbed2478 9665
df020ce0
TM
9666#undef GEN_XX2FORM
9667#define GEN_XX2FORM(name, opc2, opc3, fl2) \
9668GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
9669GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2)
9670
9671#undef GEN_XX3FORM
9672#define GEN_XX3FORM(name, opc2, opc3, fl2) \
9673GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
9674GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2), \
9675GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 0, PPC_NONE, fl2), \
9676GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 0, PPC_NONE, fl2)
9677
cd73f2c9
TM
9678#undef GEN_XX3FORM_DM
9679#define GEN_XX3FORM_DM(name, opc2, opc3) \
9680GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
9681GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
9682GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
9683GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
9684GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
9685GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
9686GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
9687GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
9688GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
9689GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
9690GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
9691GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
9692GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
9693GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
9694GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
9695GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x0C, 0, PPC_NONE, PPC2_VSX)
9696
df020ce0
TM
9697GEN_XX2FORM(xsabsdp, 0x12, 0x15, PPC2_VSX),
9698GEN_XX2FORM(xsnabsdp, 0x12, 0x16, PPC2_VSX),
9699GEN_XX2FORM(xsnegdp, 0x12, 0x17, PPC2_VSX),
9700GEN_XX3FORM(xscpsgndp, 0x00, 0x16, PPC2_VSX),
9701
cd73f2c9
TM
9702GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01),
9703
5c55ff99 9704#undef GEN_SPE
70560da7
FC
9705#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
9706 GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
9707GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9708GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9709GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9710GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9711GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
9712GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
9713GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE),
9714GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE),
9715GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE),
9716GEN_SPE(speundef, evand, 0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
9717GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9718GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9719GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9720GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
9721GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE),
9722GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE),
9723GEN_SPE(speundef, evorc, 0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE),
9724GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9725GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9726GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9727GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9728GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE),
9729GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
9730GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE),
9731GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9732GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE),
9733GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE),
9734GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE),
9735GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE),
9736
9737GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
9738GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
9739GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
9740GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
9741GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
9742GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9743GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9744GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9745GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9746GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9747GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9748GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9749GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
9750GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9751
9752GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
9753GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE),
9754GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE),
9755GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE),
9756GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
9757GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE),
9758GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9759GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9760GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9761GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE),
9762GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9763GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9764GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE),
9765GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE),
9766
9767GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
9768GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9769GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE),
9770GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE),
9771GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE),
9772GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9773GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
9774GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE),
9775GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9776GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9777GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9778GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE),
9779GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
9780GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
9781GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE),
9782GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE),
5c55ff99
BS
9783
9784#undef GEN_SPEOP_LDST
9785#define GEN_SPEOP_LDST(name, opc2, sh) \
9786GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)
9787GEN_SPEOP_LDST(evldd, 0x00, 3),
9788GEN_SPEOP_LDST(evldw, 0x01, 3),
9789GEN_SPEOP_LDST(evldh, 0x02, 3),
9790GEN_SPEOP_LDST(evlhhesplat, 0x04, 1),
9791GEN_SPEOP_LDST(evlhhousplat, 0x06, 1),
9792GEN_SPEOP_LDST(evlhhossplat, 0x07, 1),
9793GEN_SPEOP_LDST(evlwhe, 0x08, 2),
9794GEN_SPEOP_LDST(evlwhou, 0x0A, 2),
9795GEN_SPEOP_LDST(evlwhos, 0x0B, 2),
9796GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2),
9797GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2),
9798
9799GEN_SPEOP_LDST(evstdd, 0x10, 3),
9800GEN_SPEOP_LDST(evstdw, 0x11, 3),
9801GEN_SPEOP_LDST(evstdh, 0x12, 3),
9802GEN_SPEOP_LDST(evstwhe, 0x18, 2),
9803GEN_SPEOP_LDST(evstwho, 0x1A, 2),
9804GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
9805GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
9806};
9807
0411a972 9808#include "helper_regs.h"
a1389542 9809#include "translate_init.c"
79aceca5 9810
9a64fbe4 9811/*****************************************************************************/
3fc6c082 9812/* Misc PowerPC helpers */
878096ee
AF
9813void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
9814 int flags)
79aceca5 9815{
3fc6c082
FB
9816#define RGPL 4
9817#define RFPL 4
3fc6c082 9818
878096ee
AF
9819 PowerPCCPU *cpu = POWERPC_CPU(cs);
9820 CPUPPCState *env = &cpu->env;
79aceca5
FB
9821 int i;
9822
90e189ec 9823 cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR "
9a78eead 9824 TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
da91a00f 9825 env->nip, env->lr, env->ctr, cpu_read_xer(env));
90e189ec
BS
9826 cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF "
9827 TARGET_FMT_lx " idx %d\n", env->msr, env->spr[SPR_HID0],
9828 env->hflags, env->mmu_idx);
d9bce9d9 9829#if !defined(NO_TIMER_DUMP)
9a78eead 9830 cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
76a66253 9831#if !defined(CONFIG_USER_ONLY)
9a78eead 9832 " DECR %08" PRIu32
76a66253
JM
9833#endif
9834 "\n",
077fc206 9835 cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
76a66253
JM
9836#if !defined(CONFIG_USER_ONLY)
9837 , cpu_ppc_load_decr(env)
9838#endif
9839 );
077fc206 9840#endif
76a66253 9841 for (i = 0; i < 32; i++) {
3fc6c082
FB
9842 if ((i & (RGPL - 1)) == 0)
9843 cpu_fprintf(f, "GPR%02d", i);
b11ebf64 9844 cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
3fc6c082 9845 if ((i & (RGPL - 1)) == (RGPL - 1))
7fe48483 9846 cpu_fprintf(f, "\n");
76a66253 9847 }
3fc6c082 9848 cpu_fprintf(f, "CR ");
76a66253 9849 for (i = 0; i < 8; i++)
7fe48483
FB
9850 cpu_fprintf(f, "%01x", env->crf[i]);
9851 cpu_fprintf(f, " [");
76a66253
JM
9852 for (i = 0; i < 8; i++) {
9853 char a = '-';
9854 if (env->crf[i] & 0x08)
9855 a = 'L';
9856 else if (env->crf[i] & 0x04)
9857 a = 'G';
9858 else if (env->crf[i] & 0x02)
9859 a = 'E';
7fe48483 9860 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
76a66253 9861 }
90e189ec
BS
9862 cpu_fprintf(f, " ] RES " TARGET_FMT_lx "\n",
9863 env->reserve_addr);
3fc6c082
FB
9864 for (i = 0; i < 32; i++) {
9865 if ((i & (RFPL - 1)) == 0)
9866 cpu_fprintf(f, "FPR%02d", i);
26a76461 9867 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
3fc6c082 9868 if ((i & (RFPL - 1)) == (RFPL - 1))
7fe48483 9869 cpu_fprintf(f, "\n");
79aceca5 9870 }
30304420 9871 cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr);
f2e63a42 9872#if !defined(CONFIG_USER_ONLY)
90dc8812
SW
9873 cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx
9874 " PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
9875 env->spr[SPR_SRR0], env->spr[SPR_SRR1],
9876 env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);
9877
9878 cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
9879 " SPRG2 " TARGET_FMT_lx " SPRG3 " TARGET_FMT_lx "\n",
9880 env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
9881 env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);
9882
9883 cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
9884 " SPRG6 " TARGET_FMT_lx " SPRG7 " TARGET_FMT_lx "\n",
9885 env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
9886 env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
9887
9888 if (env->excp_model == POWERPC_EXCP_BOOKE) {
9889 cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
9890 " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
9891 env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
9892 env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
9893
9894 cpu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
9895 " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
9896 env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
9897 env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
9898
9899 cpu_fprintf(f, " PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
9900 " IVPR " TARGET_FMT_lx " EPCR " TARGET_FMT_lx "\n",
9901 env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
9902 env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);
9903
9904 cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
9905 " EPR " TARGET_FMT_lx "\n",
9906 env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
9907 env->spr[SPR_BOOKE_EPR]);
9908
9909 /* FSL-specific */
9910 cpu_fprintf(f, " MCAR " TARGET_FMT_lx " PID1 " TARGET_FMT_lx
9911 " PID2 " TARGET_FMT_lx " SVR " TARGET_FMT_lx "\n",
9912 env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
9913 env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);
9914
9915 /*
9916 * IVORs are left out as they are large and do not change often --
9917 * they can be read with "p $ivor0", "p $ivor1", etc.
9918 */
9919 }
9920
697ab892
DG
9921#if defined(TARGET_PPC64)
9922 if (env->flags & POWERPC_FLAG_CFAR) {
9923 cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
9924 }
9925#endif
9926
90dc8812
SW
9927 switch (env->mmu_model) {
9928 case POWERPC_MMU_32B:
9929 case POWERPC_MMU_601:
9930 case POWERPC_MMU_SOFT_6xx:
9931 case POWERPC_MMU_SOFT_74xx:
9932#if defined(TARGET_PPC64)
90dc8812
SW
9933 case POWERPC_MMU_64B:
9934#endif
9935 cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
9936 break;
01662f3e 9937 case POWERPC_MMU_BOOKE206:
90dc8812
SW
9938 cpu_fprintf(f, " MAS0 " TARGET_FMT_lx " MAS1 " TARGET_FMT_lx
9939 " MAS2 " TARGET_FMT_lx " MAS3 " TARGET_FMT_lx "\n",
9940 env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
9941 env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);
9942
9943 cpu_fprintf(f, " MAS4 " TARGET_FMT_lx " MAS6 " TARGET_FMT_lx
9944 " MAS7 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n",
9945 env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
9946 env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);
9947
9948 cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
9949 " TLB1CFG " TARGET_FMT_lx "\n",
9950 env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
9951 env->spr[SPR_BOOKE_TLB1CFG]);
9952 break;
9953 default:
9954 break;
9955 }
f2e63a42 9956#endif
79aceca5 9957
3fc6c082
FB
9958#undef RGPL
9959#undef RFPL
79aceca5
FB
9960}
9961
878096ee
AF
9962void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
9963 fprintf_function cpu_fprintf, int flags)
76a66253
JM
9964{
9965#if defined(DO_PPC_STATISTICS)
878096ee 9966 PowerPCCPU *cpu = POWERPC_CPU(cs);
c227f099 9967 opc_handler_t **t1, **t2, **t3, *handler;
76a66253
JM
9968 int op1, op2, op3;
9969
878096ee 9970 t1 = cpu->env.opcodes;
76a66253
JM
9971 for (op1 = 0; op1 < 64; op1++) {
9972 handler = t1[op1];
9973 if (is_indirect_opcode(handler)) {
9974 t2 = ind_table(handler);
9975 for (op2 = 0; op2 < 32; op2++) {
9976 handler = t2[op2];
9977 if (is_indirect_opcode(handler)) {
9978 t3 = ind_table(handler);
9979 for (op3 = 0; op3 < 32; op3++) {
9980 handler = t3[op3];
9981 if (handler->count == 0)
9982 continue;
9983 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
0bfcd599 9984 "%016" PRIx64 " %" PRId64 "\n",
76a66253
JM
9985 op1, op2, op3, op1, (op3 << 5) | op2,
9986 handler->oname,
9987 handler->count, handler->count);
9988 }
9989 } else {
9990 if (handler->count == 0)
9991 continue;
9992 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
0bfcd599 9993 "%016" PRIx64 " %" PRId64 "\n",
76a66253
JM
9994 op1, op2, op1, op2, handler->oname,
9995 handler->count, handler->count);
9996 }
9997 }
9998 } else {
9999 if (handler->count == 0)
10000 continue;
0bfcd599
BS
10001 cpu_fprintf(f, "%02x (%02x ) %16s: %016" PRIx64
10002 " %" PRId64 "\n",
76a66253
JM
10003 op1, op1, handler->oname,
10004 handler->count, handler->count);
10005 }
10006 }
10007#endif
10008}
10009
9a64fbe4 10010/*****************************************************************************/
213fe1f5 10011static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
636aa200 10012 TranslationBlock *tb,
213fe1f5 10013 bool search_pc)
79aceca5 10014{
ed2803da 10015 CPUState *cs = CPU(cpu);
213fe1f5 10016 CPUPPCState *env = &cpu->env;
9fddaa0c 10017 DisasContext ctx, *ctxp = &ctx;
c227f099 10018 opc_handler_t **table, *handler;
0fa85d43 10019 target_ulong pc_start;
79aceca5 10020 uint16_t *gen_opc_end;
a1d1bb31 10021 CPUBreakpoint *bp;
79aceca5 10022 int j, lj = -1;
2e70f6ef
PB
10023 int num_insns;
10024 int max_insns;
79aceca5
FB
10025
10026 pc_start = tb->pc;
92414b31 10027 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
046d6672 10028 ctx.nip = pc_start;
79aceca5 10029 ctx.tb = tb;
e1833e1f 10030 ctx.exception = POWERPC_EXCP_NONE;
3fc6c082 10031 ctx.spr_cb = env->spr_cb;
76db3ba4 10032 ctx.mem_idx = env->mmu_idx;
7d08d856
AJ
10033 ctx.insns_flags = env->insns_flags;
10034 ctx.insns_flags2 = env->insns_flags2;
76db3ba4
AJ
10035 ctx.access_type = -1;
10036 ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
d9bce9d9 10037#if defined(TARGET_PPC64)
e42a61f1 10038 ctx.sf_mode = msr_is_64bit(env, env->msr);
697ab892 10039 ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9a64fbe4 10040#endif
3cc62370 10041 ctx.fpu_enabled = msr_fp;
a9d9eb8f 10042 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
d26bfc9a
JM
10043 ctx.spe_enabled = msr_spe;
10044 else
10045 ctx.spe_enabled = 0;
a9d9eb8f
JM
10046 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
10047 ctx.altivec_enabled = msr_vr;
10048 else
10049 ctx.altivec_enabled = 0;
1f29871c
TM
10050 if ((env->flags & POWERPC_FLAG_VSX) && msr_vsx) {
10051 ctx.vsx_enabled = msr_vsx;
10052 } else {
10053 ctx.vsx_enabled = 0;
10054 }
d26bfc9a 10055 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8cbcb4fa 10056 ctx.singlestep_enabled = CPU_SINGLE_STEP;
d26bfc9a 10057 else
8cbcb4fa 10058 ctx.singlestep_enabled = 0;
d26bfc9a 10059 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8cbcb4fa 10060 ctx.singlestep_enabled |= CPU_BRANCH_STEP;
ed2803da 10061 if (unlikely(cs->singlestep_enabled)) {
8cbcb4fa 10062 ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
ed2803da 10063 }
3fc6c082 10064#if defined (DO_SINGLE_STEP) && 0
9a64fbe4
FB
10065 /* Single step trace mode */
10066 msr_se = 1;
10067#endif
2e70f6ef
PB
10068 num_insns = 0;
10069 max_insns = tb->cflags & CF_COUNT_MASK;
10070 if (max_insns == 0)
10071 max_insns = CF_COUNT_MASK;
10072
806f352d 10073 gen_tb_start();
9a64fbe4 10074 /* Set env in case of segfault during code fetch */
efd7f486
EV
10075 while (ctx.exception == POWERPC_EXCP_NONE
10076 && tcg_ctx.gen_opc_ptr < gen_opc_end) {
72cf2d4f
BS
10077 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
10078 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 10079 if (bp->pc == ctx.nip) {
e06fcd75 10080 gen_debug_exception(ctxp);
ea4e754f
FB
10081 break;
10082 }
10083 }
10084 }
76a66253 10085 if (unlikely(search_pc)) {
92414b31 10086 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
79aceca5
FB
10087 if (lj < j) {
10088 lj++;
10089 while (lj < j)
ab1103de 10090 tcg_ctx.gen_opc_instr_start[lj++] = 0;
79aceca5 10091 }
25983cad 10092 tcg_ctx.gen_opc_pc[lj] = ctx.nip;
ab1103de 10093 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 10094 tcg_ctx.gen_opc_icount[lj] = num_insns;
79aceca5 10095 }
d12d51d5 10096 LOG_DISAS("----------------\n");
90e189ec 10097 LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
d12d51d5 10098 ctx.nip, ctx.mem_idx, (int)msr_ir);
2e70f6ef
PB
10099 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
10100 gen_io_start();
76db3ba4 10101 if (unlikely(ctx.le_mode)) {
2f5a189c 10102 ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
056401ea 10103 } else {
2f5a189c 10104 ctx.opcode = cpu_ldl_code(env, ctx.nip);
111bfab3 10105 }
d12d51d5 10106 LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9a64fbe4 10107 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
476b6d16 10108 opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
fdefe51c 10109 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
731c54f8 10110 tcg_gen_debug_insn_start(ctx.nip);
fdefe51c 10111 }
046d6672 10112 ctx.nip += 4;
3fc6c082 10113 table = env->opcodes;
2e70f6ef 10114 num_insns++;
79aceca5
FB
10115 handler = table[opc1(ctx.opcode)];
10116 if (is_indirect_opcode(handler)) {
10117 table = ind_table(handler);
10118 handler = table[opc2(ctx.opcode)];
10119 if (is_indirect_opcode(handler)) {
10120 table = ind_table(handler);
10121 handler = table[opc3(ctx.opcode)];
10122 }
10123 }
10124 /* Is opcode *REALLY* valid ? */
76a66253 10125 if (unlikely(handler->handler == &gen_invalid)) {
93fcfe39
AL
10126 if (qemu_log_enabled()) {
10127 qemu_log("invalid/unsupported opcode: "
90e189ec
BS
10128 "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
10129 opc1(ctx.opcode), opc2(ctx.opcode),
10130 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
4b3686fa 10131 }
76a66253 10132 } else {
70560da7
FC
10133 uint32_t inval;
10134
10135 if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE) && Rc(ctx.opcode))) {
10136 inval = handler->inval2;
10137 } else {
10138 inval = handler->inval1;
10139 }
10140
10141 if (unlikely((ctx.opcode & inval) != 0)) {
93fcfe39
AL
10142 if (qemu_log_enabled()) {
10143 qemu_log("invalid bits: %08x for opcode: "
90e189ec 10144 "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
70560da7 10145 ctx.opcode & inval, opc1(ctx.opcode),
90e189ec
BS
10146 opc2(ctx.opcode), opc3(ctx.opcode),
10147 ctx.opcode, ctx.nip - 4);
76a66253 10148 }
e06fcd75 10149 gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
4b3686fa 10150 break;
79aceca5 10151 }
79aceca5 10152 }
4b3686fa 10153 (*(handler->handler))(&ctx);
76a66253
JM
10154#if defined(DO_PPC_STATISTICS)
10155 handler->count++;
10156#endif
9a64fbe4 10157 /* Check trace mode exceptions */
8cbcb4fa
AJ
10158 if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
10159 (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
10160 ctx.exception != POWERPC_SYSCALL &&
10161 ctx.exception != POWERPC_EXCP_TRAP &&
10162 ctx.exception != POWERPC_EXCP_BRANCH)) {
e06fcd75 10163 gen_exception(ctxp, POWERPC_EXCP_TRACE);
d26bfc9a 10164 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
ed2803da 10165 (cs->singlestep_enabled) ||
1b530a6d 10166 singlestep ||
2e70f6ef 10167 num_insns >= max_insns)) {
d26bfc9a
JM
10168 /* if we reach a page boundary or are single stepping, stop
10169 * generation
10170 */
8dd4983c 10171 break;
76a66253 10172 }
3fc6c082 10173 }
2e70f6ef
PB
10174 if (tb->cflags & CF_LAST_IO)
10175 gen_io_end();
e1833e1f 10176 if (ctx.exception == POWERPC_EXCP_NONE) {
c1942362 10177 gen_goto_tb(&ctx, 0, ctx.nip);
e1833e1f 10178 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
ed2803da 10179 if (unlikely(cs->singlestep_enabled)) {
e06fcd75 10180 gen_debug_exception(ctxp);
8cbcb4fa 10181 }
76a66253 10182 /* Generate the return instruction */
57fec1fe 10183 tcg_gen_exit_tb(0);
9a64fbe4 10184 }
806f352d 10185 gen_tb_end(tb, num_insns);
efd7f486 10186 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
76a66253 10187 if (unlikely(search_pc)) {
92414b31 10188 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
9a64fbe4
FB
10189 lj++;
10190 while (lj <= j)
ab1103de 10191 tcg_ctx.gen_opc_instr_start[lj++] = 0;
9a64fbe4 10192 } else {
046d6672 10193 tb->size = ctx.nip - pc_start;
2e70f6ef 10194 tb->icount = num_insns;
9a64fbe4 10195 }
d9bce9d9 10196#if defined(DEBUG_DISAS)
8fec2b8c 10197 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
76a66253 10198 int flags;
237c0af0 10199 flags = env->bfd_mach;
76db3ba4 10200 flags |= ctx.le_mode << 16;
93fcfe39 10201 qemu_log("IN: %s\n", lookup_symbol(pc_start));
f4359b9f 10202 log_target_disas(env, pc_start, ctx.nip - pc_start, flags);
93fcfe39 10203 qemu_log("\n");
9fddaa0c 10204 }
79aceca5 10205#endif
79aceca5
FB
10206}
10207
1328c2bf 10208void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
79aceca5 10209{
213fe1f5 10210 gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, false);
79aceca5
FB
10211}
10212
1328c2bf 10213void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
79aceca5 10214{
213fe1f5 10215 gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, true);
79aceca5 10216}
d2856f1a 10217
1328c2bf 10218void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
d2856f1a 10219{
25983cad 10220 env->nip = tcg_ctx.gen_opc_pc[pc_pos];
d2856f1a 10221}
This page took 2.703157 seconds and 4 git commands to generate.