]> git.proxmox.com Git - mirror_qemu.git/blame - target/ppc/translate.c
hw/ppc/e500: Move comment to more appropriate place
[mirror_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
6bd039cd 10 * version 2.1 of the License, or (at your option) any later version.
79aceca5
FB
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
8167ee88 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
79aceca5 19 */
c6a1c22b 20
0d75590d 21#include "qemu/osdep.h"
79aceca5 22#include "cpu.h"
3e00884f 23#include "internal.h"
76cad711 24#include "disas/disas.h"
63c91552 25#include "exec/exec-all.h"
dcb32f1d
PMD
26#include "tcg/tcg-op.h"
27#include "tcg/tcg-op-gvec.h"
1de7afc9 28#include "qemu/host-utils.h"
db725815 29#include "qemu/main-loop.h"
f08b6170 30#include "exec/cpu_ldst.h"
79aceca5 31
2ef6175a
RH
32#include "exec/helper-proto.h"
33#include "exec/helper-gen.h"
a7812ae4 34
b6bac4bc 35#include "exec/translator.h"
508127e2 36#include "exec/log.h"
f34ec0f6 37#include "qemu/atomic128.h"
99e964ef 38#include "spr_common.h"
eeaaefe9 39#include "power8-pmu.h"
a7e30d84 40
3e770bf7
BL
41#include "qemu/qemu-print.h"
42#include "qapi/error.h"
a7e30d84 43
8cbcb4fa
AJ
44#define CPU_SINGLE_STEP 0x1
45#define CPU_BRANCH_STEP 0x2
8cbcb4fa 46
a750fc0b 47/* Include definitions for instructions classes and implementations flags */
efe843d8 48/* #define PPC_DEBUG_DISAS */
79aceca5 49
d12d51d5 50#ifdef PPC_DEBUG_DISAS
93fcfe39 51# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
d12d51d5
AL
52#else
53# define LOG_DISAS(...) do { } while (0)
54#endif
a750fc0b
JM
55/*****************************************************************************/
56/* Code translation helpers */
c53be334 57
f78fb44e 58/* global register indexes */
efe843d8
DG
59static char cpu_reg_names[10 * 3 + 22 * 4 /* GPR */
60 + 10 * 4 + 22 * 5 /* SPE GPRh */
61 + 8 * 5 /* CRF */];
f78fb44e 62static TCGv cpu_gpr[32];
f78fb44e 63static TCGv cpu_gprh[32];
a7812ae4 64static TCGv_i32 cpu_crf[8];
bd568f18 65static TCGv cpu_nip;
6527f6ea 66static TCGv cpu_msr;
cfdcd37a
AJ
67static TCGv cpu_ctr;
68static TCGv cpu_lr;
697ab892
DG
69#if defined(TARGET_PPC64)
70static TCGv cpu_cfar;
71#endif
dd09c361 72static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca, cpu_ov32, cpu_ca32;
cf360a32 73static TCGv cpu_reserve;
253ce7b2 74static TCGv cpu_reserve_val;
30304420 75static TCGv cpu_fpscr;
a7859e89 76static TCGv_i32 cpu_access_type;
f78fb44e 77
022c62cb 78#include "exec/gen-icount.h"
2e70f6ef
PB
79
80void ppc_translate_init(void)
81{
f78fb44e 82 int i;
efe843d8 83 char *p;
2dc766da 84 size_t cpu_reg_names_size;
f78fb44e 85
f78fb44e 86 p = cpu_reg_names;
2dc766da 87 cpu_reg_names_size = sizeof(cpu_reg_names);
47e4661c
AJ
88
89 for (i = 0; i < 8; i++) {
2dc766da 90 snprintf(p, cpu_reg_names_size, "crf%d", i);
e1ccc054 91 cpu_crf[i] = tcg_global_mem_new_i32(cpu_env,
1328c2bf 92 offsetof(CPUPPCState, crf[i]), p);
47e4661c 93 p += 5;
2dc766da 94 cpu_reg_names_size -= 5;
47e4661c
AJ
95 }
96
f78fb44e 97 for (i = 0; i < 32; i++) {
2dc766da 98 snprintf(p, cpu_reg_names_size, "r%d", i);
e1ccc054 99 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
1328c2bf 100 offsetof(CPUPPCState, gpr[i]), p);
f78fb44e 101 p += (i < 10) ? 3 : 4;
2dc766da 102 cpu_reg_names_size -= (i < 10) ? 3 : 4;
2dc766da 103 snprintf(p, cpu_reg_names_size, "r%dH", i);
e1ccc054 104 cpu_gprh[i] = tcg_global_mem_new(cpu_env,
13b6a455 105 offsetof(CPUPPCState, gprh[i]), p);
f78fb44e 106 p += (i < 10) ? 4 : 5;
2dc766da 107 cpu_reg_names_size -= (i < 10) ? 4 : 5;
f78fb44e 108 }
f10dc08e 109
e1ccc054 110 cpu_nip = tcg_global_mem_new(cpu_env,
1328c2bf 111 offsetof(CPUPPCState, nip), "nip");
bd568f18 112
e1ccc054 113 cpu_msr = tcg_global_mem_new(cpu_env,
1328c2bf 114 offsetof(CPUPPCState, msr), "msr");
6527f6ea 115
e1ccc054 116 cpu_ctr = tcg_global_mem_new(cpu_env,
1328c2bf 117 offsetof(CPUPPCState, ctr), "ctr");
cfdcd37a 118
e1ccc054 119 cpu_lr = tcg_global_mem_new(cpu_env,
1328c2bf 120 offsetof(CPUPPCState, lr), "lr");
cfdcd37a 121
697ab892 122#if defined(TARGET_PPC64)
e1ccc054 123 cpu_cfar = tcg_global_mem_new(cpu_env,
1328c2bf 124 offsetof(CPUPPCState, cfar), "cfar");
697ab892
DG
125#endif
126
e1ccc054 127 cpu_xer = tcg_global_mem_new(cpu_env,
1328c2bf 128 offsetof(CPUPPCState, xer), "xer");
e1ccc054 129 cpu_so = tcg_global_mem_new(cpu_env,
da91a00f 130 offsetof(CPUPPCState, so), "SO");
e1ccc054 131 cpu_ov = tcg_global_mem_new(cpu_env,
da91a00f 132 offsetof(CPUPPCState, ov), "OV");
e1ccc054 133 cpu_ca = tcg_global_mem_new(cpu_env,
da91a00f 134 offsetof(CPUPPCState, ca), "CA");
dd09c361
ND
135 cpu_ov32 = tcg_global_mem_new(cpu_env,
136 offsetof(CPUPPCState, ov32), "OV32");
137 cpu_ca32 = tcg_global_mem_new(cpu_env,
138 offsetof(CPUPPCState, ca32), "CA32");
3d7b417e 139
e1ccc054 140 cpu_reserve = tcg_global_mem_new(cpu_env,
1328c2bf 141 offsetof(CPUPPCState, reserve_addr),
18b21a2f 142 "reserve_addr");
253ce7b2
ND
143 cpu_reserve_val = tcg_global_mem_new(cpu_env,
144 offsetof(CPUPPCState, reserve_val),
145 "reserve_val");
cf360a32 146
e1ccc054 147 cpu_fpscr = tcg_global_mem_new(cpu_env,
30304420 148 offsetof(CPUPPCState, fpscr), "fpscr");
e1571908 149
e1ccc054 150 cpu_access_type = tcg_global_mem_new_i32(cpu_env,
efe843d8
DG
151 offsetof(CPUPPCState, access_type),
152 "access_type");
2e70f6ef
PB
153}
154
79aceca5 155/* internal defines */
69b058c8 156struct DisasContext {
b6bac4bc 157 DisasContextBase base;
2c2bcb1b 158 target_ulong cia; /* current instruction address */
79aceca5 159 uint32_t opcode;
3cc62370 160 /* Routine used to access memory */
5c3ae929 161 bool pr, hv, dr, le_mode;
c5a8d8f3 162 bool lazy_tlb_flush;
5f2a6254 163 bool need_access_type;
3cc62370 164 int mem_idx;
76db3ba4 165 int access_type;
3cc62370 166 /* Translation flags */
14776ab5 167 MemOp default_tcg_memop_mask;
d9bce9d9 168#if defined(TARGET_PPC64)
5c3ae929
BH
169 bool sf_mode;
170 bool has_cfar;
9a64fbe4 171#endif
5c3ae929
BH
172 bool fpu_enabled;
173 bool altivec_enabled;
174 bool vsx_enabled;
175 bool spe_enabled;
176 bool tm_enabled;
c6fd28fd 177 bool gtse;
1db3632a 178 bool hr;
f7460df2
DHB
179 bool mmcr0_pmcc0;
180 bool mmcr0_pmcc1;
8b3d1c49
LL
181 bool mmcr0_pmcjce;
182 bool pmc_other;
46d396bd 183 bool pmu_insn_cnt;
c227f099 184 ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
ea4e754f 185 int singlestep_enabled;
0e3bf489 186 uint32_t flags;
7d08d856
AJ
187 uint64_t insns_flags;
188 uint64_t insns_flags2;
69b058c8 189};
79aceca5 190
a9b5b3d0
RH
191#define DISAS_EXIT DISAS_TARGET_0 /* exit to main loop, pc updated */
192#define DISAS_EXIT_UPDATE DISAS_TARGET_1 /* exit to main loop, pc stale */
193#define DISAS_CHAIN DISAS_TARGET_2 /* lookup next tb, pc updated */
194#define DISAS_CHAIN_UPDATE DISAS_TARGET_3 /* lookup next tb, pc stale */
195
e22c357b
DK
196/* Return true iff byteswap is needed in a scalar memop */
197static inline bool need_byteswap(const DisasContext *ctx)
198{
ee3eb3a7 199#if TARGET_BIG_ENDIAN
e22c357b
DK
200 return ctx->le_mode;
201#else
202 return !ctx->le_mode;
203#endif
204}
205
79482e5a
RH
206/* True when active word size < size of target_long. */
207#ifdef TARGET_PPC64
208# define NARROW_MODE(C) (!(C)->sf_mode)
209#else
210# define NARROW_MODE(C) 0
211#endif
212
c227f099 213struct opc_handler_t {
70560da7
FC
214 /* invalid bits for instruction 1 (Rc(opcode) == 0) */
215 uint32_t inval1;
216 /* invalid bits for instruction 2 (Rc(opcode) == 1) */
217 uint32_t inval2;
9a64fbe4 218 /* instruction type */
0487d6a8 219 uint64_t type;
a5858d7a
AG
220 /* extended instruction type */
221 uint64_t type2;
79aceca5
FB
222 /* handler */
223 void (*handler)(DisasContext *ctx);
3fc6c082 224};
79aceca5 225
0e3bf489
RK
226/* SPR load/store helpers */
227static inline void gen_load_spr(TCGv t, int reg)
228{
229 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
230}
231
232static inline void gen_store_spr(int reg, TCGv t)
233{
234 tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
235}
236
636aa200 237static inline void gen_set_access_type(DisasContext *ctx, int access_type)
a7859e89 238{
5f2a6254 239 if (ctx->need_access_type && ctx->access_type != access_type) {
76db3ba4
AJ
240 tcg_gen_movi_i32(cpu_access_type, access_type);
241 ctx->access_type = access_type;
242 }
a7859e89
AJ
243}
244
636aa200 245static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
d9bce9d9 246{
e0c8f9ce
RH
247 if (NARROW_MODE(ctx)) {
248 nip = (uint32_t)nip;
249 }
250 tcg_gen_movi_tl(cpu_nip, nip);
d9bce9d9
JM
251}
252
b9971cc5 253static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
e06fcd75
AJ
254{
255 TCGv_i32 t0, t1;
bd6fefe7 256
efe843d8
DG
257 /*
258 * These are all synchronous exceptions, we set the PC back to the
259 * faulting instruction
bd6fefe7 260 */
7a3fe174 261 gen_update_nip(ctx, ctx->cia);
e06fcd75
AJ
262 t0 = tcg_const_i32(excp);
263 t1 = tcg_const_i32(error);
e5f17ac6 264 gen_helper_raise_exception_err(cpu_env, t0, t1);
e06fcd75
AJ
265 tcg_temp_free_i32(t0);
266 tcg_temp_free_i32(t1);
3d8a5b69 267 ctx->base.is_jmp = DISAS_NORETURN;
e06fcd75 268}
e1833e1f 269
b9971cc5 270static void gen_exception(DisasContext *ctx, uint32_t excp)
e06fcd75
AJ
271{
272 TCGv_i32 t0;
bd6fefe7 273
efe843d8
DG
274 /*
275 * These are all synchronous exceptions, we set the PC back to the
276 * faulting instruction
bd6fefe7 277 */
7a3fe174 278 gen_update_nip(ctx, ctx->cia);
e06fcd75 279 t0 = tcg_const_i32(excp);
e5f17ac6 280 gen_helper_raise_exception(cpu_env, t0);
e06fcd75 281 tcg_temp_free_i32(t0);
3d8a5b69 282 ctx->base.is_jmp = DISAS_NORETURN;
e06fcd75 283}
e1833e1f 284
bd6fefe7
BH
285static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
286 target_ulong nip)
287{
288 TCGv_i32 t0;
289
290 gen_update_nip(ctx, nip);
291 t0 = tcg_const_i32(excp);
292 gen_helper_raise_exception(cpu_env, t0);
293 tcg_temp_free_i32(t0);
3d8a5b69 294 ctx->base.is_jmp = DISAS_NORETURN;
bd6fefe7
BH
295}
296
f5b6daac
RH
297static void gen_icount_io_start(DisasContext *ctx)
298{
299 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
300 gen_io_start();
301 /*
302 * An I/O instruction must be last in the TB.
303 * Chain to the next TB, and let the code from gen_tb_start
304 * decide if we need to return to the main loop.
305 * Doing this first also allows this value to be overridden.
306 */
307 ctx->base.is_jmp = DISAS_TOO_MANY;
308 }
309}
310
2fdedcbc
MF
311#if !defined(CONFIG_USER_ONLY)
312static void gen_ppc_maybe_interrupt(DisasContext *ctx)
313{
314 gen_icount_io_start(ctx);
315 gen_helper_ppc_maybe_interrupt(cpu_env);
316}
317#endif
318
e150ac89
RK
319/*
320 * Tells the caller what is the appropriate exception to generate and prepares
321 * SPR registers for this exception.
322 *
323 * The exception can be either POWERPC_EXCP_TRACE (on most PowerPCs) or
324 * POWERPC_EXCP_DEBUG (on BookE).
0e3bf489 325 */
e150ac89 326static uint32_t gen_prep_dbgex(DisasContext *ctx)
0e3bf489 327{
0e3bf489
RK
328 if (ctx->flags & POWERPC_FLAG_DE) {
329 target_ulong dbsr = 0;
e150ac89 330 if (ctx->singlestep_enabled & CPU_SINGLE_STEP) {
0e3bf489 331 dbsr = DBCR0_ICMP;
e150ac89
RK
332 } else {
333 /* Must have been branch */
0e3bf489 334 dbsr = DBCR0_BRT;
0e3bf489
RK
335 }
336 TCGv t0 = tcg_temp_new();
337 gen_load_spr(t0, SPR_BOOKE_DBSR);
338 tcg_gen_ori_tl(t0, t0, dbsr);
339 gen_store_spr(SPR_BOOKE_DBSR, t0);
340 tcg_temp_free(t0);
341 return POWERPC_EXCP_DEBUG;
342 } else {
e150ac89 343 return POWERPC_EXCP_TRACE;
0e3bf489
RK
344 }
345}
346
b9971cc5 347static void gen_debug_exception(DisasContext *ctx)
e06fcd75 348{
9498d103 349 gen_helper_raise_exception(cpu_env, tcg_constant_i32(gen_prep_dbgex(ctx)));
3d8a5b69 350 ctx->base.is_jmp = DISAS_NORETURN;
e06fcd75 351}
9a64fbe4 352
636aa200 353static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
e06fcd75 354{
9b2fadda
BH
355 /* Will be converted to program check if needed */
356 gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_INVAL | error);
357}
358
359static inline void gen_priv_exception(DisasContext *ctx, uint32_t error)
360{
361 gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_PRIV | error);
362}
363
364static inline void gen_hvpriv_exception(DisasContext *ctx, uint32_t error)
365{
366 /* Will be converted to program check if needed */
367 gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_PRIV | error);
e06fcd75 368}
a9d9eb8f 369
37f219c8
BL
370/*****************************************************************************/
371/* SPR READ/WRITE CALLBACKS */
372
a829cec3 373void spr_noaccess(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
374{
375#if 0
376 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
377 printf("ERROR: try to access SPR %d !\n", sprn);
378#endif
379}
37f219c8
BL
380
381/* #define PPC_DUMP_SPR_ACCESSES */
382
383/*
384 * Generic callbacks:
385 * do nothing but store/retrieve spr value
386 */
387static void spr_load_dump_spr(int sprn)
388{
389#ifdef PPC_DUMP_SPR_ACCESSES
390 TCGv_i32 t0 = tcg_const_i32(sprn);
391 gen_helper_load_dump_spr(cpu_env, t0);
392 tcg_temp_free_i32(t0);
393#endif
394}
395
a829cec3 396void spr_read_generic(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
397{
398 gen_load_spr(cpu_gpr[gprn], sprn);
399 spr_load_dump_spr(sprn);
400}
401
402static void spr_store_dump_spr(int sprn)
403{
404#ifdef PPC_DUMP_SPR_ACCESSES
405 TCGv_i32 t0 = tcg_const_i32(sprn);
406 gen_helper_store_dump_spr(cpu_env, t0);
407 tcg_temp_free_i32(t0);
408#endif
409}
410
a829cec3 411void spr_write_generic(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
412{
413 gen_store_spr(sprn, cpu_gpr[gprn]);
414 spr_store_dump_spr(sprn);
415}
416
7aeac354
DHB
417void spr_write_CTRL(DisasContext *ctx, int sprn, int gprn)
418{
419 spr_write_generic(ctx, sprn, gprn);
420
421 /*
422 * SPR_CTRL writes must force a new translation block,
423 * allowing the PMU to calculate the run latch events with
424 * more accuracy.
425 */
426 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
427}
428
37f219c8 429#if !defined(CONFIG_USER_ONLY)
a829cec3 430void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
431{
432#ifdef TARGET_PPC64
433 TCGv t0 = tcg_temp_new();
434 tcg_gen_ext32u_tl(t0, cpu_gpr[gprn]);
435 gen_store_spr(sprn, t0);
436 tcg_temp_free(t0);
437 spr_store_dump_spr(sprn);
438#else
439 spr_write_generic(ctx, sprn, gprn);
440#endif
441}
442
a829cec3 443void spr_write_clear(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
444{
445 TCGv t0 = tcg_temp_new();
446 TCGv t1 = tcg_temp_new();
447 gen_load_spr(t0, sprn);
448 tcg_gen_neg_tl(t1, cpu_gpr[gprn]);
449 tcg_gen_and_tl(t0, t0, t1);
450 gen_store_spr(sprn, t0);
451 tcg_temp_free(t0);
452 tcg_temp_free(t1);
453}
454
a829cec3 455void spr_access_nop(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
456{
457}
458
459#endif
460
461/* SPR common to all PowerPC */
462/* XER */
a829cec3 463void spr_read_xer(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
464{
465 TCGv dst = cpu_gpr[gprn];
466 TCGv t0 = tcg_temp_new();
467 TCGv t1 = tcg_temp_new();
468 TCGv t2 = tcg_temp_new();
469 tcg_gen_mov_tl(dst, cpu_xer);
470 tcg_gen_shli_tl(t0, cpu_so, XER_SO);
471 tcg_gen_shli_tl(t1, cpu_ov, XER_OV);
472 tcg_gen_shli_tl(t2, cpu_ca, XER_CA);
473 tcg_gen_or_tl(t0, t0, t1);
474 tcg_gen_or_tl(dst, dst, t2);
475 tcg_gen_or_tl(dst, dst, t0);
476 if (is_isa300(ctx)) {
477 tcg_gen_shli_tl(t0, cpu_ov32, XER_OV32);
478 tcg_gen_or_tl(dst, dst, t0);
479 tcg_gen_shli_tl(t0, cpu_ca32, XER_CA32);
480 tcg_gen_or_tl(dst, dst, t0);
481 }
482 tcg_temp_free(t0);
483 tcg_temp_free(t1);
484 tcg_temp_free(t2);
485}
486
a829cec3 487void spr_write_xer(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
488{
489 TCGv src = cpu_gpr[gprn];
490 /* Write all flags, while reading back check for isa300 */
491 tcg_gen_andi_tl(cpu_xer, src,
492 ~((1u << XER_SO) |
493 (1u << XER_OV) | (1u << XER_OV32) |
494 (1u << XER_CA) | (1u << XER_CA32)));
495 tcg_gen_extract_tl(cpu_ov32, src, XER_OV32, 1);
496 tcg_gen_extract_tl(cpu_ca32, src, XER_CA32, 1);
497 tcg_gen_extract_tl(cpu_so, src, XER_SO, 1);
498 tcg_gen_extract_tl(cpu_ov, src, XER_OV, 1);
499 tcg_gen_extract_tl(cpu_ca, src, XER_CA, 1);
500}
501
502/* LR */
a829cec3 503void spr_read_lr(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
504{
505 tcg_gen_mov_tl(cpu_gpr[gprn], cpu_lr);
506}
507
a829cec3 508void spr_write_lr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
509{
510 tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]);
511}
512
513/* CFAR */
514#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
a829cec3 515void spr_read_cfar(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
516{
517 tcg_gen_mov_tl(cpu_gpr[gprn], cpu_cfar);
518}
519
a829cec3 520void spr_write_cfar(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
521{
522 tcg_gen_mov_tl(cpu_cfar, cpu_gpr[gprn]);
523}
524#endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
525
526/* CTR */
a829cec3 527void spr_read_ctr(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
528{
529 tcg_gen_mov_tl(cpu_gpr[gprn], cpu_ctr);
530}
531
a829cec3 532void spr_write_ctr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
533{
534 tcg_gen_mov_tl(cpu_ctr, cpu_gpr[gprn]);
535}
536
537/* User read access to SPR */
538/* USPRx */
539/* UMMCRx */
540/* UPMCx */
541/* USIA */
542/* UDECR */
a829cec3 543void spr_read_ureg(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
544{
545 gen_load_spr(cpu_gpr[gprn], sprn + 0x10);
546}
547
548#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
a829cec3 549void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
550{
551 gen_store_spr(sprn + 0x10, cpu_gpr[gprn]);
552}
553#endif
554
555/* SPR common to all non-embedded PowerPC */
556/* DECR */
557#if !defined(CONFIG_USER_ONLY)
a829cec3 558void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
37f219c8 559{
f5b6daac 560 gen_icount_io_start(ctx);
37f219c8 561 gen_helper_load_decr(cpu_gpr[gprn], cpu_env);
37f219c8
BL
562}
563
a829cec3 564void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
37f219c8 565{
f5b6daac 566 gen_icount_io_start(ctx);
37f219c8 567 gen_helper_store_decr(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
568}
569#endif
570
571/* SPR common to all non-embedded PowerPC, except 601 */
572/* Time base */
a829cec3 573void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
37f219c8 574{
f5b6daac 575 gen_icount_io_start(ctx);
37f219c8 576 gen_helper_load_tbl(cpu_gpr[gprn], cpu_env);
37f219c8
BL
577}
578
a829cec3 579void spr_read_tbu(DisasContext *ctx, int gprn, int sprn)
37f219c8 580{
f5b6daac 581 gen_icount_io_start(ctx);
37f219c8 582 gen_helper_load_tbu(cpu_gpr[gprn], cpu_env);
37f219c8
BL
583}
584
a829cec3 585void spr_read_atbl(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
586{
587 gen_helper_load_atbl(cpu_gpr[gprn], cpu_env);
588}
589
a829cec3 590void spr_read_atbu(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
591{
592 gen_helper_load_atbu(cpu_gpr[gprn], cpu_env);
593}
594
595#if !defined(CONFIG_USER_ONLY)
a829cec3 596void spr_write_tbl(DisasContext *ctx, int sprn, int gprn)
37f219c8 597{
f5b6daac 598 gen_icount_io_start(ctx);
37f219c8 599 gen_helper_store_tbl(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
600}
601
a829cec3 602void spr_write_tbu(DisasContext *ctx, int sprn, int gprn)
37f219c8 603{
f5b6daac 604 gen_icount_io_start(ctx);
37f219c8 605 gen_helper_store_tbu(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
606}
607
a829cec3 608void spr_write_atbl(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
609{
610 gen_helper_store_atbl(cpu_env, cpu_gpr[gprn]);
611}
612
a829cec3 613void spr_write_atbu(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
614{
615 gen_helper_store_atbu(cpu_env, cpu_gpr[gprn]);
616}
617
618#if defined(TARGET_PPC64)
a829cec3 619void spr_read_purr(DisasContext *ctx, int gprn, int sprn)
37f219c8 620{
f5b6daac 621 gen_icount_io_start(ctx);
37f219c8 622 gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
37f219c8
BL
623}
624
a829cec3 625void spr_write_purr(DisasContext *ctx, int sprn, int gprn)
37f219c8 626{
f5b6daac 627 gen_icount_io_start(ctx);
37f219c8 628 gen_helper_store_purr(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
629}
630
631/* HDECR */
a829cec3 632void spr_read_hdecr(DisasContext *ctx, int gprn, int sprn)
37f219c8 633{
f5b6daac 634 gen_icount_io_start(ctx);
37f219c8 635 gen_helper_load_hdecr(cpu_gpr[gprn], cpu_env);
37f219c8
BL
636}
637
a829cec3 638void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn)
37f219c8 639{
f5b6daac 640 gen_icount_io_start(ctx);
37f219c8 641 gen_helper_store_hdecr(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
642}
643
a829cec3 644void spr_read_vtb(DisasContext *ctx, int gprn, int sprn)
37f219c8 645{
f5b6daac 646 gen_icount_io_start(ctx);
37f219c8 647 gen_helper_load_vtb(cpu_gpr[gprn], cpu_env);
37f219c8
BL
648}
649
a829cec3 650void spr_write_vtb(DisasContext *ctx, int sprn, int gprn)
37f219c8 651{
f5b6daac 652 gen_icount_io_start(ctx);
37f219c8 653 gen_helper_store_vtb(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
654}
655
a829cec3 656void spr_write_tbu40(DisasContext *ctx, int sprn, int gprn)
37f219c8 657{
f5b6daac 658 gen_icount_io_start(ctx);
37f219c8 659 gen_helper_store_tbu40(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
660}
661
662#endif
663#endif
664
665#if !defined(CONFIG_USER_ONLY)
666/* IBAT0U...IBAT0U */
667/* IBAT0L...IBAT7L */
a829cec3 668void spr_read_ibat(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
669{
670 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
671 offsetof(CPUPPCState,
672 IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
673}
674
a829cec3 675void spr_read_ibat_h(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
676{
677 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
678 offsetof(CPUPPCState,
679 IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4]));
680}
681
a829cec3 682void spr_write_ibatu(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
683{
684 TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2);
685 gen_helper_store_ibatu(cpu_env, t0, cpu_gpr[gprn]);
686 tcg_temp_free_i32(t0);
687}
688
a829cec3 689void spr_write_ibatu_h(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
690{
691 TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_IBAT4U) / 2) + 4);
692 gen_helper_store_ibatu(cpu_env, t0, cpu_gpr[gprn]);
693 tcg_temp_free_i32(t0);
694}
695
a829cec3 696void spr_write_ibatl(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
697{
698 TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0L) / 2);
699 gen_helper_store_ibatl(cpu_env, t0, cpu_gpr[gprn]);
700 tcg_temp_free_i32(t0);
701}
702
a829cec3 703void spr_write_ibatl_h(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
704{
705 TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_IBAT4L) / 2) + 4);
706 gen_helper_store_ibatl(cpu_env, t0, cpu_gpr[gprn]);
707 tcg_temp_free_i32(t0);
708}
709
710/* DBAT0U...DBAT7U */
711/* DBAT0L...DBAT7L */
a829cec3 712void spr_read_dbat(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
713{
714 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
715 offsetof(CPUPPCState,
716 DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2]));
717}
718
a829cec3 719void spr_read_dbat_h(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
720{
721 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
722 offsetof(CPUPPCState,
723 DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4]));
724}
725
a829cec3 726void spr_write_dbatu(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
727{
728 TCGv_i32 t0 = tcg_const_i32((sprn - SPR_DBAT0U) / 2);
729 gen_helper_store_dbatu(cpu_env, t0, cpu_gpr[gprn]);
730 tcg_temp_free_i32(t0);
731}
732
a829cec3 733void spr_write_dbatu_h(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
734{
735 TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_DBAT4U) / 2) + 4);
736 gen_helper_store_dbatu(cpu_env, t0, cpu_gpr[gprn]);
737 tcg_temp_free_i32(t0);
738}
739
a829cec3 740void spr_write_dbatl(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
741{
742 TCGv_i32 t0 = tcg_const_i32((sprn - SPR_DBAT0L) / 2);
743 gen_helper_store_dbatl(cpu_env, t0, cpu_gpr[gprn]);
744 tcg_temp_free_i32(t0);
745}
746
a829cec3 747void spr_write_dbatl_h(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
748{
749 TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_DBAT4L) / 2) + 4);
750 gen_helper_store_dbatl(cpu_env, t0, cpu_gpr[gprn]);
751 tcg_temp_free_i32(t0);
752}
753
754/* SDR1 */
a829cec3 755void spr_write_sdr1(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
756{
757 gen_helper_store_sdr1(cpu_env, cpu_gpr[gprn]);
758}
759
760#if defined(TARGET_PPC64)
761/* 64 bits PowerPC specific SPRs */
762/* PIDR */
a829cec3 763void spr_write_pidr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
764{
765 gen_helper_store_pidr(cpu_env, cpu_gpr[gprn]);
766}
767
a829cec3 768void spr_write_lpidr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
769{
770 gen_helper_store_lpidr(cpu_env, cpu_gpr[gprn]);
771}
772
a829cec3 773void spr_read_hior(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
774{
775 tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, excp_prefix));
776}
777
a829cec3 778void spr_write_hior(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
779{
780 TCGv t0 = tcg_temp_new();
781 tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0x3FFFFF00000ULL);
782 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_prefix));
783 tcg_temp_free(t0);
784}
a829cec3 785void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
786{
787 gen_helper_store_ptcr(cpu_env, cpu_gpr[gprn]);
788}
789
a829cec3 790void spr_write_pcr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
791{
792 gen_helper_store_pcr(cpu_env, cpu_gpr[gprn]);
793}
794
795/* DPDES */
a829cec3 796void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
797{
798 gen_helper_load_dpdes(cpu_gpr[gprn], cpu_env);
799}
800
a829cec3 801void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
802{
803 gen_helper_store_dpdes(cpu_env, cpu_gpr[gprn]);
804}
805#endif
806#endif
807
37f219c8
BL
808/* PowerPC 40x specific registers */
809#if !defined(CONFIG_USER_ONLY)
a829cec3 810void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn)
37f219c8 811{
f5b6daac 812 gen_icount_io_start(ctx);
37f219c8 813 gen_helper_load_40x_pit(cpu_gpr[gprn], cpu_env);
37f219c8
BL
814}
815
a829cec3 816void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn)
37f219c8 817{
f5b6daac 818 gen_icount_io_start(ctx);
37f219c8 819 gen_helper_store_40x_pit(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
820}
821
a829cec3 822void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn)
37f219c8 823{
f5b6daac 824 gen_icount_io_start(ctx);
37f219c8
BL
825 gen_store_spr(sprn, cpu_gpr[gprn]);
826 gen_helper_store_40x_dbcr0(cpu_env, cpu_gpr[gprn]);
827 /* We must stop translation as we may have rebooted */
d736de8f 828 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
37f219c8
BL
829}
830
a829cec3 831void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn)
37f219c8 832{
f5b6daac 833 gen_icount_io_start(ctx);
37f219c8 834 gen_helper_store_40x_sler(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
835}
836
cbd8f17d
CLG
837void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn)
838{
839 gen_icount_io_start(ctx);
840 gen_helper_store_40x_tcr(cpu_env, cpu_gpr[gprn]);
841}
842
843void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn)
844{
845 gen_icount_io_start(ctx);
846 gen_helper_store_40x_tsr(cpu_env, cpu_gpr[gprn]);
847}
848
dd69d140
CLG
849void spr_write_40x_pid(DisasContext *ctx, int sprn, int gprn)
850{
851 TCGv t0 = tcg_temp_new();
852 tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0xFF);
47822486 853 gen_helper_store_40x_pid(cpu_env, t0);
dd69d140
CLG
854 tcg_temp_free(t0);
855}
856
a829cec3 857void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn)
37f219c8 858{
f5b6daac 859 gen_icount_io_start(ctx);
37f219c8 860 gen_helper_store_booke_tcr(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
861}
862
a829cec3 863void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn)
37f219c8 864{
f5b6daac 865 gen_icount_io_start(ctx);
37f219c8 866 gen_helper_store_booke_tsr(cpu_env, cpu_gpr[gprn]);
37f219c8
BL
867}
868#endif
869
328c95fc 870/* PIR */
37f219c8 871#if !defined(CONFIG_USER_ONLY)
a829cec3 872void spr_write_pir(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
873{
874 TCGv t0 = tcg_temp_new();
875 tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0xF);
876 gen_store_spr(SPR_PIR, t0);
877 tcg_temp_free(t0);
878}
879#endif
880
881/* SPE specific registers */
a829cec3 882void spr_read_spefscr(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
883{
884 TCGv_i32 t0 = tcg_temp_new_i32();
885 tcg_gen_ld_i32(t0, cpu_env, offsetof(CPUPPCState, spe_fscr));
886 tcg_gen_extu_i32_tl(cpu_gpr[gprn], t0);
887 tcg_temp_free_i32(t0);
888}
889
a829cec3 890void spr_write_spefscr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
891{
892 TCGv_i32 t0 = tcg_temp_new_i32();
893 tcg_gen_trunc_tl_i32(t0, cpu_gpr[gprn]);
894 tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, spe_fscr));
895 tcg_temp_free_i32(t0);
896}
897
898#if !defined(CONFIG_USER_ONLY)
899/* Callback used to write the exception vector base */
a829cec3 900void spr_write_excp_prefix(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
901{
902 TCGv t0 = tcg_temp_new();
903 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUPPCState, ivpr_mask));
904 tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
905 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_prefix));
906 gen_store_spr(sprn, t0);
907 tcg_temp_free(t0);
908}
909
a829cec3 910void spr_write_excp_vector(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
911{
912 int sprn_offs;
913
914 if (sprn >= SPR_BOOKE_IVOR0 && sprn <= SPR_BOOKE_IVOR15) {
915 sprn_offs = sprn - SPR_BOOKE_IVOR0;
916 } else if (sprn >= SPR_BOOKE_IVOR32 && sprn <= SPR_BOOKE_IVOR37) {
917 sprn_offs = sprn - SPR_BOOKE_IVOR32 + 32;
918 } else if (sprn >= SPR_BOOKE_IVOR38 && sprn <= SPR_BOOKE_IVOR42) {
919 sprn_offs = sprn - SPR_BOOKE_IVOR38 + 38;
920 } else {
8e1fedf8
MF
921 qemu_log_mask(LOG_GUEST_ERROR, "Trying to write an unknown exception"
922 " vector 0x%03x\n", sprn);
923 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
37f219c8
BL
924 return;
925 }
926
927 TCGv t0 = tcg_temp_new();
928 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUPPCState, ivor_mask));
929 tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
930 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_vectors[sprn_offs]));
931 gen_store_spr(sprn, t0);
932 tcg_temp_free(t0);
933}
934#endif
935
936#ifdef TARGET_PPC64
937#ifndef CONFIG_USER_ONLY
a829cec3 938void spr_write_amr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
939{
940 TCGv t0 = tcg_temp_new();
941 TCGv t1 = tcg_temp_new();
942 TCGv t2 = tcg_temp_new();
943
944 /*
945 * Note, the HV=1 PR=0 case is handled earlier by simply using
946 * spr_write_generic for HV mode in the SPR table
947 */
948
949 /* Build insertion mask into t1 based on context */
950 if (ctx->pr) {
951 gen_load_spr(t1, SPR_UAMOR);
952 } else {
953 gen_load_spr(t1, SPR_AMOR);
954 }
955
956 /* Mask new bits into t2 */
957 tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]);
958
959 /* Load AMR and clear new bits in t0 */
960 gen_load_spr(t0, SPR_AMR);
961 tcg_gen_andc_tl(t0, t0, t1);
962
963 /* Or'in new bits and write it out */
964 tcg_gen_or_tl(t0, t0, t2);
965 gen_store_spr(SPR_AMR, t0);
966 spr_store_dump_spr(SPR_AMR);
967
968 tcg_temp_free(t0);
969 tcg_temp_free(t1);
970 tcg_temp_free(t2);
971}
972
a829cec3 973void spr_write_uamor(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
974{
975 TCGv t0 = tcg_temp_new();
976 TCGv t1 = tcg_temp_new();
977 TCGv t2 = tcg_temp_new();
978
979 /*
980 * Note, the HV=1 case is handled earlier by simply using
981 * spr_write_generic for HV mode in the SPR table
982 */
983
984 /* Build insertion mask into t1 based on context */
985 gen_load_spr(t1, SPR_AMOR);
986
987 /* Mask new bits into t2 */
988 tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]);
989
990 /* Load AMR and clear new bits in t0 */
991 gen_load_spr(t0, SPR_UAMOR);
992 tcg_gen_andc_tl(t0, t0, t1);
993
994 /* Or'in new bits and write it out */
995 tcg_gen_or_tl(t0, t0, t2);
996 gen_store_spr(SPR_UAMOR, t0);
997 spr_store_dump_spr(SPR_UAMOR);
998
999 tcg_temp_free(t0);
1000 tcg_temp_free(t1);
1001 tcg_temp_free(t2);
1002}
1003
a829cec3 1004void spr_write_iamr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1005{
1006 TCGv t0 = tcg_temp_new();
1007 TCGv t1 = tcg_temp_new();
1008 TCGv t2 = tcg_temp_new();
1009
1010 /*
1011 * Note, the HV=1 case is handled earlier by simply using
1012 * spr_write_generic for HV mode in the SPR table
1013 */
1014
1015 /* Build insertion mask into t1 based on context */
1016 gen_load_spr(t1, SPR_AMOR);
1017
1018 /* Mask new bits into t2 */
1019 tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]);
1020
1021 /* Load AMR and clear new bits in t0 */
1022 gen_load_spr(t0, SPR_IAMR);
1023 tcg_gen_andc_tl(t0, t0, t1);
1024
1025 /* Or'in new bits and write it out */
1026 tcg_gen_or_tl(t0, t0, t2);
1027 gen_store_spr(SPR_IAMR, t0);
1028 spr_store_dump_spr(SPR_IAMR);
1029
1030 tcg_temp_free(t0);
1031 tcg_temp_free(t1);
1032 tcg_temp_free(t2);
1033}
1034#endif
1035#endif
1036
1037#ifndef CONFIG_USER_ONLY
a829cec3 1038void spr_read_thrm(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
1039{
1040 gen_helper_fixup_thrm(cpu_env);
1041 gen_load_spr(cpu_gpr[gprn], sprn);
1042 spr_load_dump_spr(sprn);
1043}
1044#endif /* !CONFIG_USER_ONLY */
1045
1046#if !defined(CONFIG_USER_ONLY)
a829cec3 1047void spr_write_e500_l1csr0(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1048{
1049 TCGv t0 = tcg_temp_new();
1050
1051 tcg_gen_andi_tl(t0, cpu_gpr[gprn], L1CSR0_DCE | L1CSR0_CPE);
1052 gen_store_spr(sprn, t0);
1053 tcg_temp_free(t0);
1054}
1055
a829cec3 1056void spr_write_e500_l1csr1(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1057{
1058 TCGv t0 = tcg_temp_new();
1059
1060 tcg_gen_andi_tl(t0, cpu_gpr[gprn], L1CSR1_ICE | L1CSR1_CPE);
1061 gen_store_spr(sprn, t0);
1062 tcg_temp_free(t0);
1063}
1064
a829cec3 1065void spr_write_e500_l2csr0(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1066{
1067 TCGv t0 = tcg_temp_new();
1068
1069 tcg_gen_andi_tl(t0, cpu_gpr[gprn],
1070 ~(E500_L2CSR0_L2FI | E500_L2CSR0_L2FL | E500_L2CSR0_L2LFC));
1071 gen_store_spr(sprn, t0);
1072 tcg_temp_free(t0);
1073}
1074
a829cec3 1075void spr_write_booke206_mmucsr0(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1076{
1077 gen_helper_booke206_tlbflush(cpu_env, cpu_gpr[gprn]);
1078}
1079
a829cec3 1080void spr_write_booke_pid(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1081{
1082 TCGv_i32 t0 = tcg_const_i32(sprn);
1083 gen_helper_booke_setpid(cpu_env, t0, cpu_gpr[gprn]);
1084 tcg_temp_free_i32(t0);
1085}
a829cec3 1086void spr_write_eplc(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1087{
1088 gen_helper_booke_set_eplc(cpu_env, cpu_gpr[gprn]);
1089}
a829cec3 1090void spr_write_epsc(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1091{
1092 gen_helper_booke_set_epsc(cpu_env, cpu_gpr[gprn]);
1093}
1094
1095#endif
1096
1097#if !defined(CONFIG_USER_ONLY)
a829cec3 1098void spr_write_mas73(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1099{
1100 TCGv val = tcg_temp_new();
1101 tcg_gen_ext32u_tl(val, cpu_gpr[gprn]);
1102 gen_store_spr(SPR_BOOKE_MAS3, val);
1103 tcg_gen_shri_tl(val, cpu_gpr[gprn], 32);
1104 gen_store_spr(SPR_BOOKE_MAS7, val);
1105 tcg_temp_free(val);
1106}
1107
a829cec3 1108void spr_read_mas73(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
1109{
1110 TCGv mas7 = tcg_temp_new();
1111 TCGv mas3 = tcg_temp_new();
1112 gen_load_spr(mas7, SPR_BOOKE_MAS7);
1113 tcg_gen_shli_tl(mas7, mas7, 32);
1114 gen_load_spr(mas3, SPR_BOOKE_MAS3);
1115 tcg_gen_or_tl(cpu_gpr[gprn], mas3, mas7);
1116 tcg_temp_free(mas3);
1117 tcg_temp_free(mas7);
1118}
1119
1120#endif
1121
1122#ifdef TARGET_PPC64
1123static void gen_fscr_facility_check(DisasContext *ctx, int facility_sprn,
1124 int bit, int sprn, int cause)
1125{
1126 TCGv_i32 t1 = tcg_const_i32(bit);
1127 TCGv_i32 t2 = tcg_const_i32(sprn);
1128 TCGv_i32 t3 = tcg_const_i32(cause);
1129
1130 gen_helper_fscr_facility_check(cpu_env, t1, t2, t3);
1131
1132 tcg_temp_free_i32(t3);
1133 tcg_temp_free_i32(t2);
1134 tcg_temp_free_i32(t1);
1135}
1136
1137static void gen_msr_facility_check(DisasContext *ctx, int facility_sprn,
1138 int bit, int sprn, int cause)
1139{
1140 TCGv_i32 t1 = tcg_const_i32(bit);
1141 TCGv_i32 t2 = tcg_const_i32(sprn);
1142 TCGv_i32 t3 = tcg_const_i32(cause);
1143
1144 gen_helper_msr_facility_check(cpu_env, t1, t2, t3);
1145
1146 tcg_temp_free_i32(t3);
1147 tcg_temp_free_i32(t2);
1148 tcg_temp_free_i32(t1);
1149}
1150
a829cec3 1151void spr_read_prev_upper32(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
1152{
1153 TCGv spr_up = tcg_temp_new();
1154 TCGv spr = tcg_temp_new();
1155
1156 gen_load_spr(spr, sprn - 1);
1157 tcg_gen_shri_tl(spr_up, spr, 32);
1158 tcg_gen_ext32u_tl(cpu_gpr[gprn], spr_up);
1159
1160 tcg_temp_free(spr);
1161 tcg_temp_free(spr_up);
1162}
1163
a829cec3 1164void spr_write_prev_upper32(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1165{
1166 TCGv spr = tcg_temp_new();
1167
1168 gen_load_spr(spr, sprn - 1);
1169 tcg_gen_deposit_tl(spr, spr, cpu_gpr[gprn], 32, 32);
1170 gen_store_spr(sprn - 1, spr);
1171
1172 tcg_temp_free(spr);
1173}
1174
1175#if !defined(CONFIG_USER_ONLY)
a829cec3 1176void spr_write_hmer(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1177{
1178 TCGv hmer = tcg_temp_new();
1179
1180 gen_load_spr(hmer, sprn);
1181 tcg_gen_and_tl(hmer, cpu_gpr[gprn], hmer);
1182 gen_store_spr(sprn, hmer);
1183 spr_store_dump_spr(sprn);
1184 tcg_temp_free(hmer);
1185}
1186
a829cec3 1187void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1188{
1189 gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]);
1190}
1191#endif /* !defined(CONFIG_USER_ONLY) */
1192
a829cec3 1193void spr_read_tar(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
1194{
1195 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_TAR, sprn, FSCR_IC_TAR);
1196 spr_read_generic(ctx, gprn, sprn);
1197}
1198
a829cec3 1199void spr_write_tar(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1200{
1201 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_TAR, sprn, FSCR_IC_TAR);
1202 spr_write_generic(ctx, sprn, gprn);
1203}
1204
a829cec3 1205void spr_read_tm(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
1206{
1207 gen_msr_facility_check(ctx, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
1208 spr_read_generic(ctx, gprn, sprn);
1209}
1210
a829cec3 1211void spr_write_tm(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1212{
1213 gen_msr_facility_check(ctx, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
1214 spr_write_generic(ctx, sprn, gprn);
1215}
1216
a829cec3 1217void spr_read_tm_upper32(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
1218{
1219 gen_msr_facility_check(ctx, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
1220 spr_read_prev_upper32(ctx, gprn, sprn);
1221}
1222
a829cec3 1223void spr_write_tm_upper32(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1224{
1225 gen_msr_facility_check(ctx, SPR_FSCR, MSR_TM, sprn, FSCR_IC_TM);
1226 spr_write_prev_upper32(ctx, sprn, gprn);
1227}
1228
a829cec3 1229void spr_read_ebb(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
1230{
1231 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
1232 spr_read_generic(ctx, gprn, sprn);
1233}
1234
a829cec3 1235void spr_write_ebb(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1236{
1237 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
1238 spr_write_generic(ctx, sprn, gprn);
1239}
1240
a829cec3 1241void spr_read_ebb_upper32(DisasContext *ctx, int gprn, int sprn)
37f219c8
BL
1242{
1243 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
1244 spr_read_prev_upper32(ctx, gprn, sprn);
1245}
1246
a829cec3 1247void spr_write_ebb_upper32(DisasContext *ctx, int sprn, int gprn)
37f219c8
BL
1248{
1249 gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
1250 spr_write_prev_upper32(ctx, sprn, gprn);
1251}
1252#endif
1253
79aceca5 1254#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
a5858d7a
AG
1255GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
1256
1257#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2) \
1258GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
79aceca5 1259
c7697e1f 1260#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
a5858d7a
AG
1261GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
1262
1263#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2) \
1264GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
c7697e1f 1265
323ad19b
ND
1266#define GEN_HANDLER_E_2(name, opc1, opc2, opc3, opc4, inval, type, type2) \
1267GEN_OPCODE3(name, opc1, opc2, opc3, opc4, inval, type, type2)
1268
14fd8ab2
ND
1269#define GEN_HANDLER2_E_2(name, onam, opc1, opc2, opc3, opc4, inval, typ, typ2) \
1270GEN_OPCODE4(name, onam, opc1, opc2, opc3, opc4, inval, typ, typ2)
1271
c227f099 1272typedef struct opcode_t {
323ad19b 1273 unsigned char opc1, opc2, opc3, opc4;
1235fc06 1274#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
323ad19b 1275 unsigned char pad[4];
18fba28c 1276#endif
c227f099 1277 opc_handler_t handler;
b55266b5 1278 const char *oname;
c227f099 1279} opcode_t;
79aceca5 1280
9f0cf041
MF
1281static void gen_priv_opc(DisasContext *ctx)
1282{
1283 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
1284}
1285
9b2fadda 1286/* Helpers for priv. check */
9f0cf041
MF
1287#define GEN_PRIV(CTX) \
1288 do { \
1289 gen_priv_opc(CTX); return; \
9b2fadda
BH
1290 } while (0)
1291
1292#if defined(CONFIG_USER_ONLY)
9f0cf041
MF
1293#define CHK_HV(CTX) GEN_PRIV(CTX)
1294#define CHK_SV(CTX) GEN_PRIV(CTX)
1295#define CHK_HVRM(CTX) GEN_PRIV(CTX)
9b2fadda 1296#else
9f0cf041
MF
1297#define CHK_HV(CTX) \
1298 do { \
1299 if (unlikely(ctx->pr || !ctx->hv)) {\
1300 GEN_PRIV(CTX); \
1301 } \
9b2fadda 1302 } while (0)
9f0cf041 1303#define CHK_SV(CTX) \
9b2fadda
BH
1304 do { \
1305 if (unlikely(ctx->pr)) { \
9f0cf041 1306 GEN_PRIV(CTX); \
9b2fadda
BH
1307 } \
1308 } while (0)
9f0cf041
MF
1309#define CHK_HVRM(CTX) \
1310 do { \
1311 if (unlikely(ctx->pr || !ctx->hv || ctx->dr)) { \
1312 GEN_PRIV(CTX); \
1313 } \
b7815375 1314 } while (0)
9b2fadda
BH
1315#endif
1316
9f0cf041 1317#define CHK_NONE(CTX)
9b2fadda 1318
a750fc0b 1319/*****************************************************************************/
a750fc0b 1320/* PowerPC instructions table */
933dc6eb 1321
a5858d7a 1322#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 1323{ \
79aceca5
FB
1324 .opc1 = op1, \
1325 .opc2 = op2, \
1326 .opc3 = op3, \
323ad19b 1327 .opc4 = 0xff, \
79aceca5 1328 .handler = { \
70560da7
FC
1329 .inval1 = invl, \
1330 .type = _typ, \
1331 .type2 = _typ2, \
1332 .handler = &gen_##name, \
70560da7
FC
1333 }, \
1334 .oname = stringify(name), \
1335}
1336#define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \
1337{ \
1338 .opc1 = op1, \
1339 .opc2 = op2, \
1340 .opc3 = op3, \
323ad19b 1341 .opc4 = 0xff, \
70560da7
FC
1342 .handler = { \
1343 .inval1 = invl1, \
1344 .inval2 = invl2, \
9a64fbe4 1345 .type = _typ, \
a5858d7a 1346 .type2 = _typ2, \
79aceca5
FB
1347 .handler = &gen_##name, \
1348 }, \
3fc6c082 1349 .oname = stringify(name), \
79aceca5 1350}
a5858d7a 1351#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 1352{ \
c7697e1f
JM
1353 .opc1 = op1, \
1354 .opc2 = op2, \
1355 .opc3 = op3, \
323ad19b 1356 .opc4 = 0xff, \
c7697e1f 1357 .handler = { \
70560da7 1358 .inval1 = invl, \
c7697e1f 1359 .type = _typ, \
a5858d7a 1360 .type2 = _typ2, \
c7697e1f 1361 .handler = &gen_##name, \
c7697e1f
JM
1362 }, \
1363 .oname = onam, \
1364}
323ad19b
ND
1365#define GEN_OPCODE3(name, op1, op2, op3, op4, invl, _typ, _typ2) \
1366{ \
1367 .opc1 = op1, \
1368 .opc2 = op2, \
1369 .opc3 = op3, \
1370 .opc4 = op4, \
1371 .handler = { \
1372 .inval1 = invl, \
1373 .type = _typ, \
1374 .type2 = _typ2, \
1375 .handler = &gen_##name, \
323ad19b
ND
1376 }, \
1377 .oname = stringify(name), \
1378}
14fd8ab2
ND
1379#define GEN_OPCODE4(name, onam, op1, op2, op3, op4, invl, _typ, _typ2) \
1380{ \
1381 .opc1 = op1, \
1382 .opc2 = op2, \
1383 .opc3 = op3, \
1384 .opc4 = op4, \
1385 .handler = { \
1386 .inval1 = invl, \
1387 .type = _typ, \
1388 .type2 = _typ2, \
1389 .handler = &gen_##name, \
14fd8ab2
ND
1390 }, \
1391 .oname = onam, \
1392}
2e610050 1393
54623277 1394/* Invalid instruction */
99e300ef 1395static void gen_invalid(DisasContext *ctx)
9a64fbe4 1396{
e06fcd75 1397 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
9a64fbe4
FB
1398}
1399
c227f099 1400static opc_handler_t invalid_handler = {
70560da7
FC
1401 .inval1 = 0xFFFFFFFF,
1402 .inval2 = 0xFFFFFFFF,
9a64fbe4 1403 .type = PPC_NONE,
a5858d7a 1404 .type2 = PPC_NONE,
79aceca5
FB
1405 .handler = gen_invalid,
1406};
1407
e1571908
AJ
1408/*** Integer comparison ***/
1409
636aa200 1410static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
e1571908 1411{
2fdcb629 1412 TCGv t0 = tcg_temp_new();
b62b3686
PB
1413 TCGv t1 = tcg_temp_new();
1414 TCGv_i32 t = tcg_temp_new_i32();
e1571908 1415
b62b3686
PB
1416 tcg_gen_movi_tl(t0, CRF_EQ);
1417 tcg_gen_movi_tl(t1, CRF_LT);
efe843d8
DG
1418 tcg_gen_movcond_tl((s ? TCG_COND_LT : TCG_COND_LTU),
1419 t0, arg0, arg1, t1, t0);
b62b3686 1420 tcg_gen_movi_tl(t1, CRF_GT);
efe843d8
DG
1421 tcg_gen_movcond_tl((s ? TCG_COND_GT : TCG_COND_GTU),
1422 t0, arg0, arg1, t1, t0);
2fdcb629 1423
b62b3686
PB
1424 tcg_gen_trunc_tl_i32(t, t0);
1425 tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
1426 tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t);
2fdcb629
RH
1427
1428 tcg_temp_free(t0);
b62b3686
PB
1429 tcg_temp_free(t1);
1430 tcg_temp_free_i32(t);
e1571908
AJ
1431}
1432
636aa200 1433static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 1434{
2fdcb629 1435 TCGv t0 = tcg_const_tl(arg1);
ea363694
AJ
1436 gen_op_cmp(arg0, t0, s, crf);
1437 tcg_temp_free(t0);
e1571908
AJ
1438}
1439
636aa200 1440static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
e1571908 1441{
ea363694 1442 TCGv t0, t1;
2fdcb629
RH
1443 t0 = tcg_temp_new();
1444 t1 = tcg_temp_new();
e1571908 1445 if (s) {
ea363694
AJ
1446 tcg_gen_ext32s_tl(t0, arg0);
1447 tcg_gen_ext32s_tl(t1, arg1);
e1571908 1448 } else {
ea363694
AJ
1449 tcg_gen_ext32u_tl(t0, arg0);
1450 tcg_gen_ext32u_tl(t1, arg1);
e1571908 1451 }
ea363694
AJ
1452 gen_op_cmp(t0, t1, s, crf);
1453 tcg_temp_free(t1);
1454 tcg_temp_free(t0);
e1571908
AJ
1455}
1456
636aa200 1457static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 1458{
2fdcb629 1459 TCGv t0 = tcg_const_tl(arg1);
ea363694
AJ
1460 gen_op_cmp32(arg0, t0, s, crf);
1461 tcg_temp_free(t0);
e1571908 1462}
e1571908 1463
636aa200 1464static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
e1571908 1465{
02765534 1466 if (NARROW_MODE(ctx)) {
e1571908 1467 gen_op_cmpi32(reg, 0, 1, 0);
02765534 1468 } else {
e1571908 1469 gen_op_cmpi(reg, 0, 1, 0);
02765534 1470 }
e1571908
AJ
1471}
1472
f2442ef9
ND
1473/* cmprb - range comparison: isupper, isaplha, islower*/
1474static void gen_cmprb(DisasContext *ctx)
1475{
1476 TCGv_i32 src1 = tcg_temp_new_i32();
1477 TCGv_i32 src2 = tcg_temp_new_i32();
1478 TCGv_i32 src2lo = tcg_temp_new_i32();
1479 TCGv_i32 src2hi = tcg_temp_new_i32();
1480 TCGv_i32 crf = cpu_crf[crfD(ctx->opcode)];
1481
1482 tcg_gen_trunc_tl_i32(src1, cpu_gpr[rA(ctx->opcode)]);
1483 tcg_gen_trunc_tl_i32(src2, cpu_gpr[rB(ctx->opcode)]);
1484
1485 tcg_gen_andi_i32(src1, src1, 0xFF);
1486 tcg_gen_ext8u_i32(src2lo, src2);
1487 tcg_gen_shri_i32(src2, src2, 8);
1488 tcg_gen_ext8u_i32(src2hi, src2);
1489
1490 tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
1491 tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
1492 tcg_gen_and_i32(crf, src2lo, src2hi);
1493
1494 if (ctx->opcode & 0x00200000) {
1495 tcg_gen_shri_i32(src2, src2, 8);
1496 tcg_gen_ext8u_i32(src2lo, src2);
1497 tcg_gen_shri_i32(src2, src2, 8);
1498 tcg_gen_ext8u_i32(src2hi, src2);
1499 tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
1500 tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
1501 tcg_gen_and_i32(src2lo, src2lo, src2hi);
1502 tcg_gen_or_i32(crf, crf, src2lo);
1503 }
efa73196 1504 tcg_gen_shli_i32(crf, crf, CRF_GT_BIT);
f2442ef9
ND
1505 tcg_temp_free_i32(src1);
1506 tcg_temp_free_i32(src2);
1507 tcg_temp_free_i32(src2lo);
1508 tcg_temp_free_i32(src2hi);
1509}
1510
082ce330
ND
1511#if defined(TARGET_PPC64)
1512/* cmpeqb */
1513static void gen_cmpeqb(DisasContext *ctx)
1514{
1515 gen_helper_cmpeqb(cpu_crf[crfD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1516 cpu_gpr[rB(ctx->opcode)]);
1517}
1518#endif
1519
e1571908 1520/* isel (PowerPC 2.03 specification) */
99e300ef 1521static void gen_isel(DisasContext *ctx)
e1571908 1522{
e1571908 1523 uint32_t bi = rC(ctx->opcode);
24f9cd95
RH
1524 uint32_t mask = 0x08 >> (bi & 0x03);
1525 TCGv t0 = tcg_temp_new();
1526 TCGv zr;
e1571908 1527
24f9cd95
RH
1528 tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]);
1529 tcg_gen_andi_tl(t0, t0, mask);
1530
1531 zr = tcg_const_tl(0);
1532 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rD(ctx->opcode)], t0, zr,
1533 rA(ctx->opcode) ? cpu_gpr[rA(ctx->opcode)] : zr,
1534 cpu_gpr[rB(ctx->opcode)]);
1535 tcg_temp_free(zr);
1536 tcg_temp_free(t0);
e1571908
AJ
1537}
1538
fcfda20f
AJ
1539/* cmpb: PowerPC 2.05 specification */
1540static void gen_cmpb(DisasContext *ctx)
1541{
1542 gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
1543 cpu_gpr[rB(ctx->opcode)]);
1544}
1545
79aceca5 1546/*** Integer arithmetic ***/
79aceca5 1547
636aa200
BS
1548static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
1549 TCGv arg1, TCGv arg2, int sub)
74637406 1550{
ffe30937 1551 TCGv t0 = tcg_temp_new();
79aceca5 1552
8e7a6db9 1553 tcg_gen_xor_tl(cpu_ov, arg0, arg2);
74637406 1554 tcg_gen_xor_tl(t0, arg1, arg2);
ffe30937
RH
1555 if (sub) {
1556 tcg_gen_and_tl(cpu_ov, cpu_ov, t0);
1557 } else {
1558 tcg_gen_andc_tl(cpu_ov, cpu_ov, t0);
1559 }
1560 tcg_temp_free(t0);
02765534 1561 if (NARROW_MODE(ctx)) {
dc0ad844
ND
1562 tcg_gen_extract_tl(cpu_ov, cpu_ov, 31, 1);
1563 if (is_isa300(ctx)) {
1564 tcg_gen_mov_tl(cpu_ov32, cpu_ov);
1565 }
1566 } else {
1567 if (is_isa300(ctx)) {
1568 tcg_gen_extract_tl(cpu_ov32, cpu_ov, 31, 1);
1569 }
38a61d34 1570 tcg_gen_extract_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1, 1);
ffe30937 1571 }
ffe30937 1572 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
79aceca5
FB
1573}
1574
6b10d008
ND
1575static inline void gen_op_arith_compute_ca32(DisasContext *ctx,
1576 TCGv res, TCGv arg0, TCGv arg1,
4c5920af 1577 TCGv ca32, int sub)
6b10d008
ND
1578{
1579 TCGv t0;
1580
1581 if (!is_isa300(ctx)) {
1582 return;
1583 }
1584
1585 t0 = tcg_temp_new();
33903d0a
ND
1586 if (sub) {
1587 tcg_gen_eqv_tl(t0, arg0, arg1);
1588 } else {
1589 tcg_gen_xor_tl(t0, arg0, arg1);
1590 }
6b10d008 1591 tcg_gen_xor_tl(t0, t0, res);
4c5920af 1592 tcg_gen_extract_tl(ca32, t0, 32, 1);
6b10d008
ND
1593 tcg_temp_free(t0);
1594}
1595
74637406 1596/* Common add function */
636aa200 1597static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
4c5920af
SJS
1598 TCGv arg2, TCGv ca, TCGv ca32,
1599 bool add_ca, bool compute_ca,
b5a73f8d 1600 bool compute_ov, bool compute_rc0)
74637406 1601{
b5a73f8d 1602 TCGv t0 = ret;
d9bce9d9 1603
752d634e 1604 if (compute_ca || compute_ov) {
146de60d 1605 t0 = tcg_temp_new();
74637406 1606 }
79aceca5 1607
da91a00f 1608 if (compute_ca) {
79482e5a 1609 if (NARROW_MODE(ctx)) {
efe843d8
DG
1610 /*
1611 * Caution: a non-obvious corner case of the spec is that
1612 * we must produce the *entire* 64-bit addition, but
1613 * produce the carry into bit 32.
1614 */
79482e5a 1615 TCGv t1 = tcg_temp_new();
752d634e
RH
1616 tcg_gen_xor_tl(t1, arg1, arg2); /* add without carry */
1617 tcg_gen_add_tl(t0, arg1, arg2);
79482e5a 1618 if (add_ca) {
4c5920af 1619 tcg_gen_add_tl(t0, t0, ca);
79482e5a 1620 }
4c5920af 1621 tcg_gen_xor_tl(ca, t0, t1); /* bits changed w/ carry */
752d634e 1622 tcg_temp_free(t1);
4c5920af 1623 tcg_gen_extract_tl(ca, ca, 32, 1);
6b10d008 1624 if (is_isa300(ctx)) {
4c5920af 1625 tcg_gen_mov_tl(ca32, ca);
6b10d008 1626 }
b5a73f8d 1627 } else {
79482e5a
RH
1628 TCGv zero = tcg_const_tl(0);
1629 if (add_ca) {
4c5920af
SJS
1630 tcg_gen_add2_tl(t0, ca, arg1, zero, ca, zero);
1631 tcg_gen_add2_tl(t0, ca, t0, ca, arg2, zero);
79482e5a 1632 } else {
4c5920af 1633 tcg_gen_add2_tl(t0, ca, arg1, zero, arg2, zero);
79482e5a 1634 }
4c5920af 1635 gen_op_arith_compute_ca32(ctx, t0, arg1, arg2, ca32, 0);
79482e5a 1636 tcg_temp_free(zero);
b5a73f8d 1637 }
b5a73f8d
RH
1638 } else {
1639 tcg_gen_add_tl(t0, arg1, arg2);
1640 if (add_ca) {
4c5920af 1641 tcg_gen_add_tl(t0, t0, ca);
b5a73f8d 1642 }
da91a00f 1643 }
79aceca5 1644
74637406
AJ
1645 if (compute_ov) {
1646 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
1647 }
b5a73f8d 1648 if (unlikely(compute_rc0)) {
74637406 1649 gen_set_Rc0(ctx, t0);
b5a73f8d 1650 }
74637406 1651
11f4e8f8 1652 if (t0 != ret) {
74637406
AJ
1653 tcg_gen_mov_tl(ret, t0);
1654 tcg_temp_free(t0);
1655 }
39dd32ee 1656}
74637406 1657/* Add functions with two operands */
4c5920af 1658#define GEN_INT_ARITH_ADD(name, opc3, ca, add_ca, compute_ca, compute_ov) \
b5a73f8d 1659static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
1660{ \
1661 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
1662 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
4c5920af 1663 ca, glue(ca, 32), \
b5a73f8d 1664 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
1665}
1666/* Add functions with one operand and one immediate */
4c5920af 1667#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, ca, \
74637406 1668 add_ca, compute_ca, compute_ov) \
b5a73f8d 1669static void glue(gen_, name)(DisasContext *ctx) \
74637406 1670{ \
b5a73f8d 1671 TCGv t0 = tcg_const_tl(const_val); \
74637406
AJ
1672 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
1673 cpu_gpr[rA(ctx->opcode)], t0, \
4c5920af 1674 ca, glue(ca, 32), \
b5a73f8d 1675 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
1676 tcg_temp_free(t0); \
1677}
1678
1679/* add add. addo addo. */
4c5920af
SJS
1680GEN_INT_ARITH_ADD(add, 0x08, cpu_ca, 0, 0, 0)
1681GEN_INT_ARITH_ADD(addo, 0x18, cpu_ca, 0, 0, 1)
74637406 1682/* addc addc. addco addco. */
4c5920af
SJS
1683GEN_INT_ARITH_ADD(addc, 0x00, cpu_ca, 0, 1, 0)
1684GEN_INT_ARITH_ADD(addco, 0x10, cpu_ca, 0, 1, 1)
74637406 1685/* adde adde. addeo addeo. */
4c5920af
SJS
1686GEN_INT_ARITH_ADD(adde, 0x04, cpu_ca, 1, 1, 0)
1687GEN_INT_ARITH_ADD(addeo, 0x14, cpu_ca, 1, 1, 1)
74637406 1688/* addme addme. addmeo addmeo. */
4c5920af
SJS
1689GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, cpu_ca, 1, 1, 0)
1690GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, cpu_ca, 1, 1, 1)
1691/* addex */
1692GEN_INT_ARITH_ADD(addex, 0x05, cpu_ov, 1, 1, 0);
74637406 1693/* addze addze. addzeo addzeo.*/
4c5920af
SJS
1694GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, cpu_ca, 1, 1, 0)
1695GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, cpu_ca, 1, 1, 1)
74637406 1696/* addic addic.*/
b5a73f8d 1697static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
d9bce9d9 1698{
b5a73f8d
RH
1699 TCGv c = tcg_const_tl(SIMM(ctx->opcode));
1700 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
4c5920af 1701 c, cpu_ca, cpu_ca32, 0, 1, 0, compute_rc0);
b5a73f8d 1702 tcg_temp_free(c);
d9bce9d9 1703}
99e300ef
BS
1704
1705static void gen_addic(DisasContext *ctx)
d9bce9d9 1706{
b5a73f8d 1707 gen_op_addic(ctx, 0);
d9bce9d9 1708}
e8eaa2c0
BS
1709
1710static void gen_addic_(DisasContext *ctx)
d9bce9d9 1711{
b5a73f8d 1712 gen_op_addic(ctx, 1);
d9bce9d9 1713}
99e300ef 1714
636aa200
BS
1715static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
1716 TCGv arg2, int sign, int compute_ov)
d9bce9d9 1717{
b07c32dc
ND
1718 TCGv_i32 t0 = tcg_temp_new_i32();
1719 TCGv_i32 t1 = tcg_temp_new_i32();
1720 TCGv_i32 t2 = tcg_temp_new_i32();
1721 TCGv_i32 t3 = tcg_temp_new_i32();
74637406 1722
2ef1b120
AJ
1723 tcg_gen_trunc_tl_i32(t0, arg1);
1724 tcg_gen_trunc_tl_i32(t1, arg2);
74637406 1725 if (sign) {
b07c32dc
ND
1726 tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t0, INT_MIN);
1727 tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, -1);
1728 tcg_gen_and_i32(t2, t2, t3);
1729 tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, 0);
1730 tcg_gen_or_i32(t2, t2, t3);
1731 tcg_gen_movi_i32(t3, 0);
1732 tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1);
1733 tcg_gen_div_i32(t3, t0, t1);
1734 tcg_gen_extu_i32_tl(ret, t3);
74637406 1735 } else {
b07c32dc
ND
1736 tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t1, 0);
1737 tcg_gen_movi_i32(t3, 0);
1738 tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1);
1739 tcg_gen_divu_i32(t3, t0, t1);
1740 tcg_gen_extu_i32_tl(ret, t3);
74637406
AJ
1741 }
1742 if (compute_ov) {
b07c32dc 1743 tcg_gen_extu_i32_tl(cpu_ov, t2);
c44027ff
ND
1744 if (is_isa300(ctx)) {
1745 tcg_gen_extu_i32_tl(cpu_ov32, t2);
1746 }
b07c32dc 1747 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
74637406 1748 }
a7812ae4
PB
1749 tcg_temp_free_i32(t0);
1750 tcg_temp_free_i32(t1);
b07c32dc
ND
1751 tcg_temp_free_i32(t2);
1752 tcg_temp_free_i32(t3);
1753
efe843d8 1754 if (unlikely(Rc(ctx->opcode) != 0)) {
74637406 1755 gen_set_Rc0(ctx, ret);
efe843d8 1756 }
d9bce9d9 1757}
74637406
AJ
1758/* Div functions */
1759#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
efe843d8 1760static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
1761{ \
1762 gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)], \
1763 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1764 sign, compute_ov); \
1765}
1766/* divwu divwu. divwuo divwuo. */
1767GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
1768GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
1769/* divw divw. divwo divwo. */
1770GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
1771GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
98d1eb27
TM
1772
1773/* div[wd]eu[o][.] */
1774#define GEN_DIVE(name, hlpr, compute_ov) \
1775static void gen_##name(DisasContext *ctx) \
1776{ \
1777 TCGv_i32 t0 = tcg_const_i32(compute_ov); \
1778 gen_helper_##hlpr(cpu_gpr[rD(ctx->opcode)], cpu_env, \
1779 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0); \
1780 tcg_temp_free_i32(t0); \
1781 if (unlikely(Rc(ctx->opcode) != 0)) { \
1782 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); \
1783 } \
1784}
1785
6a4fda33
TM
1786GEN_DIVE(divweu, divweu, 0);
1787GEN_DIVE(divweuo, divweu, 1);
a98eb9e9
TM
1788GEN_DIVE(divwe, divwe, 0);
1789GEN_DIVE(divweo, divwe, 1);
6a4fda33 1790
d9bce9d9 1791#if defined(TARGET_PPC64)
636aa200
BS
1792static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
1793 TCGv arg2, int sign, int compute_ov)
d9bce9d9 1794{
4110b586
ND
1795 TCGv_i64 t0 = tcg_temp_new_i64();
1796 TCGv_i64 t1 = tcg_temp_new_i64();
1797 TCGv_i64 t2 = tcg_temp_new_i64();
1798 TCGv_i64 t3 = tcg_temp_new_i64();
74637406 1799
4110b586
ND
1800 tcg_gen_mov_i64(t0, arg1);
1801 tcg_gen_mov_i64(t1, arg2);
74637406 1802 if (sign) {
4110b586
ND
1803 tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t0, INT64_MIN);
1804 tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, -1);
1805 tcg_gen_and_i64(t2, t2, t3);
1806 tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, 0);
1807 tcg_gen_or_i64(t2, t2, t3);
1808 tcg_gen_movi_i64(t3, 0);
1809 tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1);
1810 tcg_gen_div_i64(ret, t0, t1);
74637406 1811 } else {
4110b586
ND
1812 tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t1, 0);
1813 tcg_gen_movi_i64(t3, 0);
1814 tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1);
1815 tcg_gen_divu_i64(ret, t0, t1);
74637406
AJ
1816 }
1817 if (compute_ov) {
4110b586 1818 tcg_gen_mov_tl(cpu_ov, t2);
c44027ff
ND
1819 if (is_isa300(ctx)) {
1820 tcg_gen_mov_tl(cpu_ov32, t2);
1821 }
4110b586 1822 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
74637406 1823 }
4110b586
ND
1824 tcg_temp_free_i64(t0);
1825 tcg_temp_free_i64(t1);
1826 tcg_temp_free_i64(t2);
1827 tcg_temp_free_i64(t3);
1828
efe843d8 1829 if (unlikely(Rc(ctx->opcode) != 0)) {
74637406 1830 gen_set_Rc0(ctx, ret);
efe843d8 1831 }
d9bce9d9 1832}
4110b586 1833
74637406 1834#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
efe843d8 1835static void glue(gen_, name)(DisasContext *ctx) \
74637406 1836{ \
2ef1b120
AJ
1837 gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)], \
1838 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1839 sign, compute_ov); \
74637406 1840}
c44027ff 1841/* divdu divdu. divduo divduo. */
74637406
AJ
1842GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1843GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
c44027ff 1844/* divd divd. divdo divdo. */
74637406
AJ
1845GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1846GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
98d1eb27
TM
1847
1848GEN_DIVE(divdeu, divdeu, 0);
1849GEN_DIVE(divdeuo, divdeu, 1);
e44259b6
TM
1850GEN_DIVE(divde, divde, 0);
1851GEN_DIVE(divdeo, divde, 1);
d9bce9d9 1852#endif
74637406 1853
af2c6620
ND
1854static inline void gen_op_arith_modw(DisasContext *ctx, TCGv ret, TCGv arg1,
1855 TCGv arg2, int sign)
1856{
1857 TCGv_i32 t0 = tcg_temp_new_i32();
1858 TCGv_i32 t1 = tcg_temp_new_i32();
1859
1860 tcg_gen_trunc_tl_i32(t0, arg1);
1861 tcg_gen_trunc_tl_i32(t1, arg2);
1862 if (sign) {
1863 TCGv_i32 t2 = tcg_temp_new_i32();
1864 TCGv_i32 t3 = tcg_temp_new_i32();
1865 tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t0, INT_MIN);
1866 tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, -1);
1867 tcg_gen_and_i32(t2, t2, t3);
1868 tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, 0);
1869 tcg_gen_or_i32(t2, t2, t3);
1870 tcg_gen_movi_i32(t3, 0);
1871 tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1);
1872 tcg_gen_rem_i32(t3, t0, t1);
1873 tcg_gen_ext_i32_tl(ret, t3);
1874 tcg_temp_free_i32(t2);
1875 tcg_temp_free_i32(t3);
1876 } else {
1877 TCGv_i32 t2 = tcg_const_i32(1);
1878 TCGv_i32 t3 = tcg_const_i32(0);
1879 tcg_gen_movcond_i32(TCG_COND_EQ, t1, t1, t3, t2, t1);
1880 tcg_gen_remu_i32(t3, t0, t1);
1881 tcg_gen_extu_i32_tl(ret, t3);
1882 tcg_temp_free_i32(t2);
1883 tcg_temp_free_i32(t3);
1884 }
1885 tcg_temp_free_i32(t0);
1886 tcg_temp_free_i32(t1);
1887}
1888
1889#define GEN_INT_ARITH_MODW(name, opc3, sign) \
1890static void glue(gen_, name)(DisasContext *ctx) \
1891{ \
1892 gen_op_arith_modw(ctx, cpu_gpr[rD(ctx->opcode)], \
1893 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1894 sign); \
1895}
1896
1897GEN_INT_ARITH_MODW(moduw, 0x08, 0);
1898GEN_INT_ARITH_MODW(modsw, 0x18, 1);
1899
063cf14f
ND
1900#if defined(TARGET_PPC64)
1901static inline void gen_op_arith_modd(DisasContext *ctx, TCGv ret, TCGv arg1,
1902 TCGv arg2, int sign)
1903{
1904 TCGv_i64 t0 = tcg_temp_new_i64();
1905 TCGv_i64 t1 = tcg_temp_new_i64();
1906
1907 tcg_gen_mov_i64(t0, arg1);
1908 tcg_gen_mov_i64(t1, arg2);
1909 if (sign) {
1910 TCGv_i64 t2 = tcg_temp_new_i64();
1911 TCGv_i64 t3 = tcg_temp_new_i64();
1912 tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t0, INT64_MIN);
1913 tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, -1);
1914 tcg_gen_and_i64(t2, t2, t3);
1915 tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, 0);
1916 tcg_gen_or_i64(t2, t2, t3);
1917 tcg_gen_movi_i64(t3, 0);
1918 tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1);
1919 tcg_gen_rem_i64(ret, t0, t1);
1920 tcg_temp_free_i64(t2);
1921 tcg_temp_free_i64(t3);
1922 } else {
1923 TCGv_i64 t2 = tcg_const_i64(1);
1924 TCGv_i64 t3 = tcg_const_i64(0);
1925 tcg_gen_movcond_i64(TCG_COND_EQ, t1, t1, t3, t2, t1);
1926 tcg_gen_remu_i64(ret, t0, t1);
1927 tcg_temp_free_i64(t2);
1928 tcg_temp_free_i64(t3);
1929 }
1930 tcg_temp_free_i64(t0);
1931 tcg_temp_free_i64(t1);
1932}
1933
1934#define GEN_INT_ARITH_MODD(name, opc3, sign) \
1935static void glue(gen_, name)(DisasContext *ctx) \
1936{ \
1937 gen_op_arith_modd(ctx, cpu_gpr[rD(ctx->opcode)], \
1938 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1939 sign); \
1940}
1941
1942GEN_INT_ARITH_MODD(modud, 0x08, 0);
1943GEN_INT_ARITH_MODD(modsd, 0x18, 1);
1944#endif
1945
74637406 1946/* mulhw mulhw. */
99e300ef 1947static void gen_mulhw(DisasContext *ctx)
d9bce9d9 1948{
23ad1d5d
RH
1949 TCGv_i32 t0 = tcg_temp_new_i32();
1950 TCGv_i32 t1 = tcg_temp_new_i32();
74637406 1951
23ad1d5d
RH
1952 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1953 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1954 tcg_gen_muls2_i32(t0, t1, t0, t1);
1955 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1956 tcg_temp_free_i32(t0);
1957 tcg_temp_free_i32(t1);
efe843d8 1958 if (unlikely(Rc(ctx->opcode) != 0)) {
74637406 1959 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
efe843d8 1960 }
d9bce9d9 1961}
99e300ef 1962
54623277 1963/* mulhwu mulhwu. */
99e300ef 1964static void gen_mulhwu(DisasContext *ctx)
d9bce9d9 1965{
23ad1d5d
RH
1966 TCGv_i32 t0 = tcg_temp_new_i32();
1967 TCGv_i32 t1 = tcg_temp_new_i32();
74637406 1968
23ad1d5d
RH
1969 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
1970 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
1971 tcg_gen_mulu2_i32(t0, t1, t0, t1);
1972 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
1973 tcg_temp_free_i32(t0);
1974 tcg_temp_free_i32(t1);
efe843d8 1975 if (unlikely(Rc(ctx->opcode) != 0)) {
74637406 1976 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
efe843d8 1977 }
d9bce9d9 1978}
99e300ef 1979
54623277 1980/* mullw mullw. */
99e300ef 1981static void gen_mullw(DisasContext *ctx)
d9bce9d9 1982{
1fa74845
TM
1983#if defined(TARGET_PPC64)
1984 TCGv_i64 t0, t1;
1985 t0 = tcg_temp_new_i64();
1986 t1 = tcg_temp_new_i64();
1987 tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1988 tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1989 tcg_gen_mul_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
1990 tcg_temp_free(t0);
1991 tcg_temp_free(t1);
1992#else
03039e5e
TM
1993 tcg_gen_mul_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1994 cpu_gpr[rB(ctx->opcode)]);
1fa74845 1995#endif
efe843d8 1996 if (unlikely(Rc(ctx->opcode) != 0)) {
74637406 1997 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
efe843d8 1998 }
d9bce9d9 1999}
99e300ef 2000
54623277 2001/* mullwo mullwo. */
99e300ef 2002static void gen_mullwo(DisasContext *ctx)
d9bce9d9 2003{
e4a2c846
RH
2004 TCGv_i32 t0 = tcg_temp_new_i32();
2005 TCGv_i32 t1 = tcg_temp_new_i32();
74637406 2006
e4a2c846
RH
2007 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);
2008 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);
2009 tcg_gen_muls2_i32(t0, t1, t0, t1);
f11ebbf8 2010#if defined(TARGET_PPC64)
26977876
TM
2011 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);
2012#else
2013 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], t0);
f11ebbf8 2014#endif
e4a2c846
RH
2015
2016 tcg_gen_sari_i32(t0, t0, 31);
2017 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1);
2018 tcg_gen_extu_i32_tl(cpu_ov, t0);
61aa9a69
ND
2019 if (is_isa300(ctx)) {
2020 tcg_gen_mov_tl(cpu_ov32, cpu_ov);
2021 }
e4a2c846
RH
2022 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
2023
2024 tcg_temp_free_i32(t0);
2025 tcg_temp_free_i32(t1);
efe843d8 2026 if (unlikely(Rc(ctx->opcode) != 0)) {
74637406 2027 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
efe843d8 2028 }
d9bce9d9 2029}
99e300ef 2030
54623277 2031/* mulli */
99e300ef 2032static void gen_mulli(DisasContext *ctx)
d9bce9d9 2033{
74637406
AJ
2034 tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
2035 SIMM(ctx->opcode));
d9bce9d9 2036}
23ad1d5d 2037
d9bce9d9 2038#if defined(TARGET_PPC64)
74637406 2039/* mulhd mulhd. */
23ad1d5d
RH
2040static void gen_mulhd(DisasContext *ctx)
2041{
2042 TCGv lo = tcg_temp_new();
2043 tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)],
2044 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2045 tcg_temp_free(lo);
2046 if (unlikely(Rc(ctx->opcode) != 0)) {
2047 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2048 }
2049}
2050
74637406 2051/* mulhdu mulhdu. */
23ad1d5d
RH
2052static void gen_mulhdu(DisasContext *ctx)
2053{
2054 TCGv lo = tcg_temp_new();
2055 tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)],
2056 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2057 tcg_temp_free(lo);
2058 if (unlikely(Rc(ctx->opcode) != 0)) {
2059 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2060 }
2061}
99e300ef 2062
54623277 2063/* mulld mulld. */
99e300ef 2064static void gen_mulld(DisasContext *ctx)
d9bce9d9 2065{
74637406
AJ
2066 tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
2067 cpu_gpr[rB(ctx->opcode)]);
efe843d8 2068 if (unlikely(Rc(ctx->opcode) != 0)) {
74637406 2069 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
efe843d8 2070 }
d9bce9d9 2071}
d15f74fb 2072
74637406 2073/* mulldo mulldo. */
d15f74fb
BS
2074static void gen_mulldo(DisasContext *ctx)
2075{
22ffad31
TM
2076 TCGv_i64 t0 = tcg_temp_new_i64();
2077 TCGv_i64 t1 = tcg_temp_new_i64();
2078
2079 tcg_gen_muls2_i64(t0, t1, cpu_gpr[rA(ctx->opcode)],
2080 cpu_gpr[rB(ctx->opcode)]);
2081 tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], t0);
2082
2083 tcg_gen_sari_i64(t0, t0, 63);
2084 tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1);
61aa9a69
ND
2085 if (is_isa300(ctx)) {
2086 tcg_gen_mov_tl(cpu_ov32, cpu_ov);
2087 }
22ffad31
TM
2088 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
2089
2090 tcg_temp_free_i64(t0);
2091 tcg_temp_free_i64(t1);
2092
d15f74fb
BS
2093 if (unlikely(Rc(ctx->opcode) != 0)) {
2094 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2095 }
2096}
d9bce9d9 2097#endif
74637406 2098
74637406 2099/* Common subf function */
636aa200 2100static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
b5a73f8d
RH
2101 TCGv arg2, bool add_ca, bool compute_ca,
2102 bool compute_ov, bool compute_rc0)
79aceca5 2103{
b5a73f8d 2104 TCGv t0 = ret;
79aceca5 2105
752d634e 2106 if (compute_ca || compute_ov) {
b5a73f8d 2107 t0 = tcg_temp_new();
da91a00f 2108 }
74637406 2109
79482e5a
RH
2110 if (compute_ca) {
2111 /* dest = ~arg1 + arg2 [+ ca]. */
2112 if (NARROW_MODE(ctx)) {
efe843d8
DG
2113 /*
2114 * Caution: a non-obvious corner case of the spec is that
2115 * we must produce the *entire* 64-bit addition, but
2116 * produce the carry into bit 32.
2117 */
79482e5a 2118 TCGv inv1 = tcg_temp_new();
752d634e 2119 TCGv t1 = tcg_temp_new();
79482e5a 2120 tcg_gen_not_tl(inv1, arg1);
79482e5a 2121 if (add_ca) {
752d634e 2122 tcg_gen_add_tl(t0, arg2, cpu_ca);
79482e5a 2123 } else {
752d634e 2124 tcg_gen_addi_tl(t0, arg2, 1);
79482e5a 2125 }
752d634e 2126 tcg_gen_xor_tl(t1, arg2, inv1); /* add without carry */
79482e5a 2127 tcg_gen_add_tl(t0, t0, inv1);
c80d1df5 2128 tcg_temp_free(inv1);
752d634e
RH
2129 tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changes w/ carry */
2130 tcg_temp_free(t1);
e2622073 2131 tcg_gen_extract_tl(cpu_ca, cpu_ca, 32, 1);
33903d0a
ND
2132 if (is_isa300(ctx)) {
2133 tcg_gen_mov_tl(cpu_ca32, cpu_ca);
2134 }
79482e5a 2135 } else if (add_ca) {
08f4a0f7
RH
2136 TCGv zero, inv1 = tcg_temp_new();
2137 tcg_gen_not_tl(inv1, arg1);
b5a73f8d
RH
2138 zero = tcg_const_tl(0);
2139 tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero);
08f4a0f7 2140 tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero);
4c5920af 2141 gen_op_arith_compute_ca32(ctx, t0, inv1, arg2, cpu_ca32, 0);
b5a73f8d 2142 tcg_temp_free(zero);
08f4a0f7 2143 tcg_temp_free(inv1);
b5a73f8d 2144 } else {
79482e5a 2145 tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
b5a73f8d 2146 tcg_gen_sub_tl(t0, arg2, arg1);
4c5920af 2147 gen_op_arith_compute_ca32(ctx, t0, arg1, arg2, cpu_ca32, 1);
b5a73f8d 2148 }
79482e5a 2149 } else if (add_ca) {
efe843d8
DG
2150 /*
2151 * Since we're ignoring carry-out, we can simplify the
2152 * standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1.
2153 */
79482e5a
RH
2154 tcg_gen_sub_tl(t0, arg2, arg1);
2155 tcg_gen_add_tl(t0, t0, cpu_ca);
2156 tcg_gen_subi_tl(t0, t0, 1);
79aceca5 2157 } else {
b5a73f8d 2158 tcg_gen_sub_tl(t0, arg2, arg1);
74637406 2159 }
b5a73f8d 2160
74637406
AJ
2161 if (compute_ov) {
2162 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
2163 }
b5a73f8d 2164 if (unlikely(compute_rc0)) {
74637406 2165 gen_set_Rc0(ctx, t0);
b5a73f8d 2166 }
74637406 2167
11f4e8f8 2168 if (t0 != ret) {
74637406
AJ
2169 tcg_gen_mov_tl(ret, t0);
2170 tcg_temp_free(t0);
79aceca5 2171 }
79aceca5 2172}
74637406
AJ
2173/* Sub functions with Two operands functions */
2174#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
b5a73f8d 2175static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
2176{ \
2177 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
2178 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
b5a73f8d 2179 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
2180}
2181/* Sub functions with one operand and one immediate */
2182#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
2183 add_ca, compute_ca, compute_ov) \
b5a73f8d 2184static void glue(gen_, name)(DisasContext *ctx) \
74637406 2185{ \
b5a73f8d 2186 TCGv t0 = tcg_const_tl(const_val); \
74637406
AJ
2187 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
2188 cpu_gpr[rA(ctx->opcode)], t0, \
b5a73f8d 2189 add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
74637406
AJ
2190 tcg_temp_free(t0); \
2191}
2192/* subf subf. subfo subfo. */
2193GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
2194GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
2195/* subfc subfc. subfco subfco. */
2196GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
2197GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
2198/* subfe subfe. subfeo subfo. */
2199GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
2200GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
2201/* subfme subfme. subfmeo subfmeo. */
2202GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
2203GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
2204/* subfze subfze. subfzeo subfzeo.*/
2205GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
2206GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
99e300ef 2207
54623277 2208/* subfic */
99e300ef 2209static void gen_subfic(DisasContext *ctx)
79aceca5 2210{
b5a73f8d
RH
2211 TCGv c = tcg_const_tl(SIMM(ctx->opcode));
2212 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
2213 c, 0, 1, 0, 0);
2214 tcg_temp_free(c);
79aceca5
FB
2215}
2216
fd3f0081
RH
2217/* neg neg. nego nego. */
2218static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
2219{
2220 TCGv zero = tcg_const_tl(0);
2221 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
2222 zero, 0, 0, compute_ov, Rc(ctx->opcode));
2223 tcg_temp_free(zero);
2224}
2225
2226static void gen_neg(DisasContext *ctx)
2227{
1480d71c
ND
2228 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
2229 if (unlikely(Rc(ctx->opcode))) {
2230 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
2231 }
fd3f0081
RH
2232}
2233
2234static void gen_nego(DisasContext *ctx)
2235{
2236 gen_op_arith_neg(ctx, 1);
2237}
2238
79aceca5 2239/*** Integer logical ***/
26d67362 2240#define GEN_LOGICAL2(name, tcg_op, opc, type) \
efe843d8 2241static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 2242{ \
26d67362
AJ
2243 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \
2244 cpu_gpr[rB(ctx->opcode)]); \
76a66253 2245 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 2246 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5 2247}
79aceca5 2248
26d67362 2249#define GEN_LOGICAL1(name, tcg_op, opc, type) \
efe843d8 2250static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 2251{ \
26d67362 2252 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \
76a66253 2253 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 2254 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5
FB
2255}
2256
2257/* and & and. */
26d67362 2258GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
79aceca5 2259/* andc & andc. */
26d67362 2260GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
e8eaa2c0 2261
54623277 2262/* andi. */
e8eaa2c0 2263static void gen_andi_(DisasContext *ctx)
79aceca5 2264{
efe843d8
DG
2265 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2266 UIMM(ctx->opcode));
26d67362 2267 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 2268}
e8eaa2c0 2269
54623277 2270/* andis. */
e8eaa2c0 2271static void gen_andis_(DisasContext *ctx)
79aceca5 2272{
efe843d8
DG
2273 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2274 UIMM(ctx->opcode) << 16);
26d67362 2275 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 2276}
99e300ef 2277
54623277 2278/* cntlzw */
99e300ef 2279static void gen_cntlzw(DisasContext *ctx)
26d67362 2280{
9b8514e5
RH
2281 TCGv_i32 t = tcg_temp_new_i32();
2282
2283 tcg_gen_trunc_tl_i32(t, cpu_gpr[rS(ctx->opcode)]);
2284 tcg_gen_clzi_i32(t, t, 32);
2285 tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t);
2286 tcg_temp_free_i32(t);
2287
efe843d8 2288 if (unlikely(Rc(ctx->opcode) != 0)) {
2e31f5d3 2289 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
efe843d8 2290 }
26d67362 2291}
b35344e4
ND
2292
2293/* cnttzw */
2294static void gen_cnttzw(DisasContext *ctx)
2295{
9b8514e5
RH
2296 TCGv_i32 t = tcg_temp_new_i32();
2297
2298 tcg_gen_trunc_tl_i32(t, cpu_gpr[rS(ctx->opcode)]);
2299 tcg_gen_ctzi_i32(t, t, 32);
2300 tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t);
2301 tcg_temp_free_i32(t);
2302
b35344e4
ND
2303 if (unlikely(Rc(ctx->opcode) != 0)) {
2304 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2305 }
2306}
2307
79aceca5 2308/* eqv & eqv. */
26d67362 2309GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
79aceca5 2310/* extsb & extsb. */
26d67362 2311GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
79aceca5 2312/* extsh & extsh. */
26d67362 2313GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
79aceca5 2314/* nand & nand. */
26d67362 2315GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
79aceca5 2316/* nor & nor. */
26d67362 2317GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
99e300ef 2318
7f2b1744 2319#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
b68e60e6
BH
2320static void gen_pause(DisasContext *ctx)
2321{
2322 TCGv_i32 t0 = tcg_const_i32(0);
2323 tcg_gen_st_i32(t0, cpu_env,
2324 -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
2325 tcg_temp_free_i32(t0);
2326
2327 /* Stop translation, this gives other CPUs a chance to run */
b6bac4bc 2328 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
b68e60e6
BH
2329}
2330#endif /* defined(TARGET_PPC64) */
2331
54623277 2332/* or & or. */
99e300ef 2333static void gen_or(DisasContext *ctx)
9a64fbe4 2334{
76a66253
JM
2335 int rs, ra, rb;
2336
2337 rs = rS(ctx->opcode);
2338 ra = rA(ctx->opcode);
2339 rb = rB(ctx->opcode);
2340 /* Optimisation for mr. ri case */
2341 if (rs != ra || rs != rb) {
efe843d8 2342 if (rs != rb) {
26d67362 2343 tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
efe843d8 2344 } else {
26d67362 2345 tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
efe843d8
DG
2346 }
2347 if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 2348 gen_set_Rc0(ctx, cpu_gpr[ra]);
efe843d8 2349 }
76a66253 2350 } else if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 2351 gen_set_Rc0(ctx, cpu_gpr[rs]);
c80f84e3 2352#if defined(TARGET_PPC64)
9e196938 2353 } else if (rs != 0) { /* 0 is nop */
26d67362
AJ
2354 int prio = 0;
2355
c80f84e3
JM
2356 switch (rs) {
2357 case 1:
2358 /* Set process priority to low */
26d67362 2359 prio = 2;
c80f84e3
JM
2360 break;
2361 case 6:
2362 /* Set process priority to medium-low */
26d67362 2363 prio = 3;
c80f84e3
JM
2364 break;
2365 case 2:
2366 /* Set process priority to normal */
26d67362 2367 prio = 4;
c80f84e3 2368 break;
be147d08
JM
2369#if !defined(CONFIG_USER_ONLY)
2370 case 31:
c47493f2 2371 if (!ctx->pr) {
be147d08 2372 /* Set process priority to very low */
26d67362 2373 prio = 1;
be147d08
JM
2374 }
2375 break;
2376 case 5:
c47493f2 2377 if (!ctx->pr) {
be147d08 2378 /* Set process priority to medium-hight */
26d67362 2379 prio = 5;
be147d08
JM
2380 }
2381 break;
2382 case 3:
c47493f2 2383 if (!ctx->pr) {
be147d08 2384 /* Set process priority to high */
26d67362 2385 prio = 6;
be147d08
JM
2386 }
2387 break;
be147d08 2388 case 7:
b68e60e6 2389 if (ctx->hv && !ctx->pr) {
be147d08 2390 /* Set process priority to very high */
26d67362 2391 prio = 7;
be147d08
JM
2392 }
2393 break;
be147d08 2394#endif
c80f84e3 2395 default:
c80f84e3
JM
2396 break;
2397 }
26d67362 2398 if (prio) {
a7812ae4 2399 TCGv t0 = tcg_temp_new();
54cdcae6 2400 gen_load_spr(t0, SPR_PPR);
ea363694
AJ
2401 tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
2402 tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
54cdcae6 2403 gen_store_spr(SPR_PPR, t0);
ea363694 2404 tcg_temp_free(t0);
9e196938 2405 }
7f2b1744 2406#if !defined(CONFIG_USER_ONLY)
efe843d8
DG
2407 /*
2408 * Pause out of TCG otherwise spin loops with smt_low eat too
2409 * much CPU and the kernel hangs. This applies to all
2410 * encodings other than no-op, e.g., miso(rs=26), yield(27),
2411 * mdoio(29), mdoom(30), and all currently undefined.
9e196938
AL
2412 */
2413 gen_pause(ctx);
7f2b1744 2414#endif
c80f84e3 2415#endif
9a64fbe4 2416 }
9a64fbe4 2417}
79aceca5 2418/* orc & orc. */
26d67362 2419GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
99e300ef 2420
54623277 2421/* xor & xor. */
99e300ef 2422static void gen_xor(DisasContext *ctx)
9a64fbe4 2423{
9a64fbe4 2424 /* Optimisation for "set to zero" case */
efe843d8
DG
2425 if (rS(ctx->opcode) != rB(ctx->opcode)) {
2426 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2427 cpu_gpr[rB(ctx->opcode)]);
2428 } else {
26d67362 2429 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
efe843d8
DG
2430 }
2431 if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 2432 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
efe843d8 2433 }
9a64fbe4 2434}
99e300ef 2435
54623277 2436/* ori */
99e300ef 2437static void gen_ori(DisasContext *ctx)
79aceca5 2438{
76a66253 2439 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 2440
9a64fbe4 2441 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
9a64fbe4 2442 return;
76a66253 2443 }
26d67362 2444 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5 2445}
99e300ef 2446
54623277 2447/* oris */
99e300ef 2448static void gen_oris(DisasContext *ctx)
79aceca5 2449{
76a66253 2450 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 2451
9a64fbe4
FB
2452 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
2453 /* NOP */
2454 return;
76a66253 2455 }
efe843d8
DG
2456 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2457 uimm << 16);
79aceca5 2458}
99e300ef 2459
54623277 2460/* xori */
99e300ef 2461static void gen_xori(DisasContext *ctx)
79aceca5 2462{
76a66253 2463 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
2464
2465 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
2466 /* NOP */
2467 return;
2468 }
26d67362 2469 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5 2470}
99e300ef 2471
54623277 2472/* xoris */
99e300ef 2473static void gen_xoris(DisasContext *ctx)
79aceca5 2474{
76a66253 2475 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
2476
2477 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
2478 /* NOP */
2479 return;
2480 }
efe843d8
DG
2481 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
2482 uimm << 16);
79aceca5 2483}
99e300ef 2484
54623277 2485/* popcntb : PowerPC 2.03 specification */
99e300ef 2486static void gen_popcntb(DisasContext *ctx)
d9bce9d9 2487{
eaabeef2
DG
2488 gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2489}
2490
2491static void gen_popcntw(DisasContext *ctx)
2492{
79770002 2493#if defined(TARGET_PPC64)
eaabeef2 2494 gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
79770002
RH
2495#else
2496 tcg_gen_ctpop_i32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
2497#endif
eaabeef2
DG
2498}
2499
d9bce9d9 2500#if defined(TARGET_PPC64)
eaabeef2
DG
2501/* popcntd: PowerPC 2.06 specification */
2502static void gen_popcntd(DisasContext *ctx)
2503{
79770002 2504 tcg_gen_ctpop_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
d9bce9d9 2505}
eaabeef2 2506#endif
d9bce9d9 2507
725bcec2
AJ
2508/* prtyw: PowerPC 2.05 specification */
2509static void gen_prtyw(DisasContext *ctx)
2510{
2511 TCGv ra = cpu_gpr[rA(ctx->opcode)];
2512 TCGv rs = cpu_gpr[rS(ctx->opcode)];
2513 TCGv t0 = tcg_temp_new();
2514 tcg_gen_shri_tl(t0, rs, 16);
2515 tcg_gen_xor_tl(ra, rs, t0);
2516 tcg_gen_shri_tl(t0, ra, 8);
2517 tcg_gen_xor_tl(ra, ra, t0);
2518 tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL);
2519 tcg_temp_free(t0);
2520}
2521
2522#if defined(TARGET_PPC64)
2523/* prtyd: PowerPC 2.05 specification */
2524static void gen_prtyd(DisasContext *ctx)
2525{
2526 TCGv ra = cpu_gpr[rA(ctx->opcode)];
2527 TCGv rs = cpu_gpr[rS(ctx->opcode)];
2528 TCGv t0 = tcg_temp_new();
2529 tcg_gen_shri_tl(t0, rs, 32);
2530 tcg_gen_xor_tl(ra, rs, t0);
2531 tcg_gen_shri_tl(t0, ra, 16);
2532 tcg_gen_xor_tl(ra, ra, t0);
2533 tcg_gen_shri_tl(t0, ra, 8);
2534 tcg_gen_xor_tl(ra, ra, t0);
2535 tcg_gen_andi_tl(ra, ra, 1);
2536 tcg_temp_free(t0);
2537}
2538#endif
2539
86ba37ed
TM
2540#if defined(TARGET_PPC64)
2541/* bpermd */
2542static void gen_bpermd(DisasContext *ctx)
2543{
2544 gen_helper_bpermd(cpu_gpr[rA(ctx->opcode)],
2545 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
2546}
2547#endif
2548
d9bce9d9
JM
2549#if defined(TARGET_PPC64)
2550/* extsw & extsw. */
26d67362 2551GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
99e300ef 2552
54623277 2553/* cntlzd */
99e300ef 2554static void gen_cntlzd(DisasContext *ctx)
26d67362 2555{
9b8514e5 2556 tcg_gen_clzi_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 64);
efe843d8 2557 if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 2558 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
efe843d8 2559 }
26d67362 2560}
e91d95b2
SD
2561
2562/* cnttzd */
2563static void gen_cnttzd(DisasContext *ctx)
2564{
9b8514e5 2565 tcg_gen_ctzi_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 64);
e91d95b2
SD
2566 if (unlikely(Rc(ctx->opcode) != 0)) {
2567 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2568 }
2569}
fec5c62a
RB
2570
2571/* darn */
2572static void gen_darn(DisasContext *ctx)
2573{
2574 int l = L(ctx->opcode);
2575
7e4357f6 2576 if (l > 2) {
fec5c62a 2577 tcg_gen_movi_i64(cpu_gpr[rD(ctx->opcode)], -1);
7e4357f6 2578 } else {
f5b6daac 2579 gen_icount_io_start(ctx);
7e4357f6
RH
2580 if (l == 0) {
2581 gen_helper_darn32(cpu_gpr[rD(ctx->opcode)]);
2582 } else {
2583 /* Return 64-bit random for both CRN and RRN */
2584 gen_helper_darn64(cpu_gpr[rD(ctx->opcode)]);
2585 }
fec5c62a
RB
2586 }
2587}
d9bce9d9
JM
2588#endif
2589
79aceca5 2590/*** Integer rotate ***/
99e300ef 2591
54623277 2592/* rlwimi & rlwimi. */
99e300ef 2593static void gen_rlwimi(DisasContext *ctx)
79aceca5 2594{
63ae0915
RH
2595 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2596 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2597 uint32_t sh = SH(ctx->opcode);
2598 uint32_t mb = MB(ctx->opcode);
2599 uint32_t me = ME(ctx->opcode);
2600
efe843d8 2601 if (sh == (31 - me) && mb <= me) {
63ae0915 2602 tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
d03ef511 2603 } else {
d03ef511 2604 target_ulong mask;
c4f6a4a3 2605 bool mask_in_32b = true;
a7812ae4 2606 TCGv t1;
63ae0915 2607
76a66253 2608#if defined(TARGET_PPC64)
d03ef511
AJ
2609 mb += 32;
2610 me += 32;
76a66253 2611#endif
d03ef511 2612 mask = MASK(mb, me);
63ae0915 2613
c4f6a4a3
DB
2614#if defined(TARGET_PPC64)
2615 if (mask > 0xffffffffu) {
2616 mask_in_32b = false;
2617 }
2618#endif
a7812ae4 2619 t1 = tcg_temp_new();
c4f6a4a3 2620 if (mask_in_32b) {
2e11b15d
RH
2621 TCGv_i32 t0 = tcg_temp_new_i32();
2622 tcg_gen_trunc_tl_i32(t0, t_rs);
2623 tcg_gen_rotli_i32(t0, t0, sh);
2624 tcg_gen_extu_i32_tl(t1, t0);
2625 tcg_temp_free_i32(t0);
2626 } else {
2627#if defined(TARGET_PPC64)
2628 tcg_gen_deposit_i64(t1, t_rs, t_rs, 32, 32);
2629 tcg_gen_rotli_i64(t1, t1, sh);
2630#else
2631 g_assert_not_reached();
2632#endif
2633 }
63ae0915
RH
2634
2635 tcg_gen_andi_tl(t1, t1, mask);
2636 tcg_gen_andi_tl(t_ra, t_ra, ~mask);
2637 tcg_gen_or_tl(t_ra, t_ra, t1);
d03ef511
AJ
2638 tcg_temp_free(t1);
2639 }
63ae0915
RH
2640 if (unlikely(Rc(ctx->opcode) != 0)) {
2641 gen_set_Rc0(ctx, t_ra);
2642 }
79aceca5 2643}
99e300ef 2644
54623277 2645/* rlwinm & rlwinm. */
99e300ef 2646static void gen_rlwinm(DisasContext *ctx)
79aceca5 2647{
63ae0915
RH
2648 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2649 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
7b4d326f
RH
2650 int sh = SH(ctx->opcode);
2651 int mb = MB(ctx->opcode);
2652 int me = ME(ctx->opcode);
2653 int len = me - mb + 1;
2654 int rsh = (32 - sh) & 31;
2655
2656 if (sh != 0 && len > 0 && me == (31 - sh)) {
2657 tcg_gen_deposit_z_tl(t_ra, t_rs, sh, len);
2658 } else if (me == 31 && rsh + len <= 32) {
2659 tcg_gen_extract_tl(t_ra, t_rs, rsh, len);
d03ef511 2660 } else {
2e11b15d 2661 target_ulong mask;
c4f6a4a3 2662 bool mask_in_32b = true;
76a66253 2663#if defined(TARGET_PPC64)
d03ef511
AJ
2664 mb += 32;
2665 me += 32;
76a66253 2666#endif
2e11b15d 2667 mask = MASK(mb, me);
c4f6a4a3
DB
2668#if defined(TARGET_PPC64)
2669 if (mask > 0xffffffffu) {
2670 mask_in_32b = false;
2671 }
2672#endif
2673 if (mask_in_32b) {
94f040aa
VC
2674 if (sh == 0) {
2675 tcg_gen_andi_tl(t_ra, t_rs, mask);
2676 } else {
2677 TCGv_i32 t0 = tcg_temp_new_i32();
2678 tcg_gen_trunc_tl_i32(t0, t_rs);
2679 tcg_gen_rotli_i32(t0, t0, sh);
2680 tcg_gen_andi_i32(t0, t0, mask);
2681 tcg_gen_extu_i32_tl(t_ra, t0);
2682 tcg_temp_free_i32(t0);
2683 }
2e11b15d
RH
2684 } else {
2685#if defined(TARGET_PPC64)
2686 tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
2687 tcg_gen_rotli_i64(t_ra, t_ra, sh);
2688 tcg_gen_andi_i64(t_ra, t_ra, mask);
2689#else
2690 g_assert_not_reached();
2691#endif
63ae0915
RH
2692 }
2693 }
2694 if (unlikely(Rc(ctx->opcode) != 0)) {
2695 gen_set_Rc0(ctx, t_ra);
d03ef511 2696 }
79aceca5 2697}
99e300ef 2698
54623277 2699/* rlwnm & rlwnm. */
99e300ef 2700static void gen_rlwnm(DisasContext *ctx)
79aceca5 2701{
63ae0915
RH
2702 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2703 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2704 TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
2705 uint32_t mb = MB(ctx->opcode);
2706 uint32_t me = ME(ctx->opcode);
2e11b15d 2707 target_ulong mask;
c4f6a4a3 2708 bool mask_in_32b = true;
57fca134 2709
54843a58 2710#if defined(TARGET_PPC64)
63ae0915
RH
2711 mb += 32;
2712 me += 32;
54843a58 2713#endif
2e11b15d
RH
2714 mask = MASK(mb, me);
2715
c4f6a4a3
DB
2716#if defined(TARGET_PPC64)
2717 if (mask > 0xffffffffu) {
2718 mask_in_32b = false;
2719 }
2720#endif
2721 if (mask_in_32b) {
2e11b15d
RH
2722 TCGv_i32 t0 = tcg_temp_new_i32();
2723 TCGv_i32 t1 = tcg_temp_new_i32();
2724 tcg_gen_trunc_tl_i32(t0, t_rb);
2725 tcg_gen_trunc_tl_i32(t1, t_rs);
2726 tcg_gen_andi_i32(t0, t0, 0x1f);
2727 tcg_gen_rotl_i32(t1, t1, t0);
2728 tcg_gen_extu_i32_tl(t_ra, t1);
2729 tcg_temp_free_i32(t0);
2730 tcg_temp_free_i32(t1);
2731 } else {
2732#if defined(TARGET_PPC64)
2733 TCGv_i64 t0 = tcg_temp_new_i64();
2734 tcg_gen_andi_i64(t0, t_rb, 0x1f);
2735 tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
2736 tcg_gen_rotl_i64(t_ra, t_ra, t0);
2737 tcg_temp_free_i64(t0);
2738#else
2739 g_assert_not_reached();
2740#endif
2741 }
57fca134 2742
2e11b15d 2743 tcg_gen_andi_tl(t_ra, t_ra, mask);
63ae0915
RH
2744
2745 if (unlikely(Rc(ctx->opcode) != 0)) {
2746 gen_set_Rc0(ctx, t_ra);
79aceca5 2747 }
79aceca5
FB
2748}
2749
d9bce9d9
JM
2750#if defined(TARGET_PPC64)
2751#define GEN_PPC64_R2(name, opc1, opc2) \
e8eaa2c0 2752static void glue(gen_, name##0)(DisasContext *ctx) \
d9bce9d9
JM
2753{ \
2754 gen_##name(ctx, 0); \
2755} \
e8eaa2c0
BS
2756 \
2757static void glue(gen_, name##1)(DisasContext *ctx) \
d9bce9d9
JM
2758{ \
2759 gen_##name(ctx, 1); \
2760}
2761#define GEN_PPC64_R4(name, opc1, opc2) \
e8eaa2c0 2762static void glue(gen_, name##0)(DisasContext *ctx) \
d9bce9d9
JM
2763{ \
2764 gen_##name(ctx, 0, 0); \
2765} \
e8eaa2c0
BS
2766 \
2767static void glue(gen_, name##1)(DisasContext *ctx) \
d9bce9d9
JM
2768{ \
2769 gen_##name(ctx, 0, 1); \
2770} \
e8eaa2c0
BS
2771 \
2772static void glue(gen_, name##2)(DisasContext *ctx) \
d9bce9d9
JM
2773{ \
2774 gen_##name(ctx, 1, 0); \
2775} \
e8eaa2c0
BS
2776 \
2777static void glue(gen_, name##3)(DisasContext *ctx) \
d9bce9d9
JM
2778{ \
2779 gen_##name(ctx, 1, 1); \
2780}
51789c41 2781
a7b2c8b9 2782static void gen_rldinm(DisasContext *ctx, int mb, int me, int sh)
51789c41 2783{
a7b2c8b9
RH
2784 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2785 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
7b4d326f
RH
2786 int len = me - mb + 1;
2787 int rsh = (64 - sh) & 63;
a7b2c8b9 2788
7b4d326f
RH
2789 if (sh != 0 && len > 0 && me == (63 - sh)) {
2790 tcg_gen_deposit_z_tl(t_ra, t_rs, sh, len);
2791 } else if (me == 63 && rsh + len <= 64) {
2792 tcg_gen_extract_tl(t_ra, t_rs, rsh, len);
d03ef511 2793 } else {
a7b2c8b9
RH
2794 tcg_gen_rotli_tl(t_ra, t_rs, sh);
2795 tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
2796 }
2797 if (unlikely(Rc(ctx->opcode) != 0)) {
2798 gen_set_Rc0(ctx, t_ra);
51789c41 2799 }
51789c41 2800}
a7b2c8b9 2801
d9bce9d9 2802/* rldicl - rldicl. */
636aa200 2803static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
d9bce9d9 2804{
51789c41 2805 uint32_t sh, mb;
d9bce9d9 2806
9d53c753
JM
2807 sh = SH(ctx->opcode) | (shn << 5);
2808 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 2809 gen_rldinm(ctx, mb, 63, sh);
d9bce9d9 2810}
51789c41 2811GEN_PPC64_R4(rldicl, 0x1E, 0x00);
a7b2c8b9 2812
d9bce9d9 2813/* rldicr - rldicr. */
636aa200 2814static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
d9bce9d9 2815{
51789c41 2816 uint32_t sh, me;
d9bce9d9 2817
9d53c753
JM
2818 sh = SH(ctx->opcode) | (shn << 5);
2819 me = MB(ctx->opcode) | (men << 5);
51789c41 2820 gen_rldinm(ctx, 0, me, sh);
d9bce9d9 2821}
51789c41 2822GEN_PPC64_R4(rldicr, 0x1E, 0x02);
a7b2c8b9 2823
d9bce9d9 2824/* rldic - rldic. */
636aa200 2825static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
d9bce9d9 2826{
51789c41 2827 uint32_t sh, mb;
d9bce9d9 2828
9d53c753
JM
2829 sh = SH(ctx->opcode) | (shn << 5);
2830 mb = MB(ctx->opcode) | (mbn << 5);
51789c41
JM
2831 gen_rldinm(ctx, mb, 63 - sh, sh);
2832}
2833GEN_PPC64_R4(rldic, 0x1E, 0x04);
2834
a7b2c8b9 2835static void gen_rldnm(DisasContext *ctx, int mb, int me)
51789c41 2836{
a7b2c8b9
RH
2837 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2838 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2839 TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
54843a58 2840 TCGv t0;
d03ef511 2841
a7812ae4 2842 t0 = tcg_temp_new();
a7b2c8b9
RH
2843 tcg_gen_andi_tl(t0, t_rb, 0x3f);
2844 tcg_gen_rotl_tl(t_ra, t_rs, t0);
54843a58 2845 tcg_temp_free(t0);
a7b2c8b9
RH
2846
2847 tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me));
2848 if (unlikely(Rc(ctx->opcode) != 0)) {
2849 gen_set_Rc0(ctx, t_ra);
2850 }
d9bce9d9 2851}
51789c41 2852
d9bce9d9 2853/* rldcl - rldcl. */
636aa200 2854static inline void gen_rldcl(DisasContext *ctx, int mbn)
d9bce9d9 2855{
51789c41 2856 uint32_t mb;
d9bce9d9 2857
9d53c753 2858 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 2859 gen_rldnm(ctx, mb, 63);
d9bce9d9 2860}
36081602 2861GEN_PPC64_R2(rldcl, 0x1E, 0x08);
a7b2c8b9 2862
d9bce9d9 2863/* rldcr - rldcr. */
636aa200 2864static inline void gen_rldcr(DisasContext *ctx, int men)
d9bce9d9 2865{
51789c41 2866 uint32_t me;
d9bce9d9 2867
9d53c753 2868 me = MB(ctx->opcode) | (men << 5);
51789c41 2869 gen_rldnm(ctx, 0, me);
d9bce9d9 2870}
36081602 2871GEN_PPC64_R2(rldcr, 0x1E, 0x09);
a7b2c8b9 2872
d9bce9d9 2873/* rldimi - rldimi. */
a7b2c8b9 2874static void gen_rldimi(DisasContext *ctx, int mbn, int shn)
d9bce9d9 2875{
a7b2c8b9
RH
2876 TCGv t_ra = cpu_gpr[rA(ctx->opcode)];
2877 TCGv t_rs = cpu_gpr[rS(ctx->opcode)];
2878 uint32_t sh = SH(ctx->opcode) | (shn << 5);
2879 uint32_t mb = MB(ctx->opcode) | (mbn << 5);
2880 uint32_t me = 63 - sh;
d9bce9d9 2881
a7b2c8b9
RH
2882 if (mb <= me) {
2883 tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
d03ef511 2884 } else {
a7b2c8b9
RH
2885 target_ulong mask = MASK(mb, me);
2886 TCGv t1 = tcg_temp_new();
d03ef511 2887
a7b2c8b9
RH
2888 tcg_gen_rotli_tl(t1, t_rs, sh);
2889 tcg_gen_andi_tl(t1, t1, mask);
2890 tcg_gen_andi_tl(t_ra, t_ra, ~mask);
2891 tcg_gen_or_tl(t_ra, t_ra, t1);
d03ef511 2892 tcg_temp_free(t1);
51789c41 2893 }
a7b2c8b9
RH
2894 if (unlikely(Rc(ctx->opcode) != 0)) {
2895 gen_set_Rc0(ctx, t_ra);
2896 }
d9bce9d9 2897}
36081602 2898GEN_PPC64_R4(rldimi, 0x1E, 0x06);
d9bce9d9
JM
2899#endif
2900
79aceca5 2901/*** Integer shift ***/
99e300ef 2902
54623277 2903/* slw & slw. */
99e300ef 2904static void gen_slw(DisasContext *ctx)
26d67362 2905{
7fd6bf7d 2906 TCGv t0, t1;
26d67362 2907
7fd6bf7d
AJ
2908 t0 = tcg_temp_new();
2909 /* AND rS with a mask that is 0 when rB >= 0x20 */
2910#if defined(TARGET_PPC64)
2911 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
2912 tcg_gen_sari_tl(t0, t0, 0x3f);
2913#else
2914 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
2915 tcg_gen_sari_tl(t0, t0, 0x1f);
2916#endif
2917 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2918 t1 = tcg_temp_new();
2919 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
2920 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
2921 tcg_temp_free(t1);
fea0c503 2922 tcg_temp_free(t0);
7fd6bf7d 2923 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
efe843d8 2924 if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 2925 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
efe843d8 2926 }
26d67362 2927}
99e300ef 2928
54623277 2929/* sraw & sraw. */
99e300ef 2930static void gen_sraw(DisasContext *ctx)
26d67362 2931{
d15f74fb 2932 gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
a7812ae4 2933 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
efe843d8 2934 if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 2935 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
efe843d8 2936 }
26d67362 2937}
99e300ef 2938
54623277 2939/* srawi & srawi. */
99e300ef 2940static void gen_srawi(DisasContext *ctx)
79aceca5 2941{
26d67362 2942 int sh = SH(ctx->opcode);
ba4af3e4
RH
2943 TCGv dst = cpu_gpr[rA(ctx->opcode)];
2944 TCGv src = cpu_gpr[rS(ctx->opcode)];
2945 if (sh == 0) {
34a0fad1 2946 tcg_gen_ext32s_tl(dst, src);
da91a00f 2947 tcg_gen_movi_tl(cpu_ca, 0);
af1c259f
SD
2948 if (is_isa300(ctx)) {
2949 tcg_gen_movi_tl(cpu_ca32, 0);
2950 }
26d67362 2951 } else {
ba4af3e4
RH
2952 TCGv t0;
2953 tcg_gen_ext32s_tl(dst, src);
2954 tcg_gen_andi_tl(cpu_ca, dst, (1ULL << sh) - 1);
2955 t0 = tcg_temp_new();
2956 tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1);
2957 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
2958 tcg_temp_free(t0);
2959 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
af1c259f
SD
2960 if (is_isa300(ctx)) {
2961 tcg_gen_mov_tl(cpu_ca32, cpu_ca);
2962 }
ba4af3e4
RH
2963 tcg_gen_sari_tl(dst, dst, sh);
2964 }
2965 if (unlikely(Rc(ctx->opcode) != 0)) {
2966 gen_set_Rc0(ctx, dst);
d9bce9d9 2967 }
79aceca5 2968}
99e300ef 2969
54623277 2970/* srw & srw. */
99e300ef 2971static void gen_srw(DisasContext *ctx)
26d67362 2972{
fea0c503 2973 TCGv t0, t1;
d9bce9d9 2974
7fd6bf7d
AJ
2975 t0 = tcg_temp_new();
2976 /* AND rS with a mask that is 0 when rB >= 0x20 */
2977#if defined(TARGET_PPC64)
2978 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
2979 tcg_gen_sari_tl(t0, t0, 0x3f);
2980#else
2981 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
2982 tcg_gen_sari_tl(t0, t0, 0x1f);
2983#endif
2984 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
2985 tcg_gen_ext32u_tl(t0, t0);
a7812ae4 2986 t1 = tcg_temp_new();
7fd6bf7d
AJ
2987 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
2988 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
fea0c503 2989 tcg_temp_free(t1);
fea0c503 2990 tcg_temp_free(t0);
efe843d8 2991 if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 2992 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
efe843d8 2993 }
26d67362 2994}
54623277 2995
d9bce9d9
JM
2996#if defined(TARGET_PPC64)
2997/* sld & sld. */
99e300ef 2998static void gen_sld(DisasContext *ctx)
26d67362 2999{
7fd6bf7d 3000 TCGv t0, t1;
26d67362 3001
7fd6bf7d
AJ
3002 t0 = tcg_temp_new();
3003 /* AND rS with a mask that is 0 when rB >= 0x40 */
3004 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
3005 tcg_gen_sari_tl(t0, t0, 0x3f);
3006 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
3007 t1 = tcg_temp_new();
3008 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
3009 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
3010 tcg_temp_free(t1);
fea0c503 3011 tcg_temp_free(t0);
efe843d8 3012 if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 3013 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
efe843d8 3014 }
26d67362 3015}
99e300ef 3016
54623277 3017/* srad & srad. */
99e300ef 3018static void gen_srad(DisasContext *ctx)
26d67362 3019{
d15f74fb 3020 gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
a7812ae4 3021 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
efe843d8 3022 if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 3023 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
efe843d8 3024 }
26d67362 3025}
d9bce9d9 3026/* sradi & sradi. */
636aa200 3027static inline void gen_sradi(DisasContext *ctx, int n)
d9bce9d9 3028{
26d67362 3029 int sh = SH(ctx->opcode) + (n << 5);
ba4af3e4
RH
3030 TCGv dst = cpu_gpr[rA(ctx->opcode)];
3031 TCGv src = cpu_gpr[rS(ctx->opcode)];
3032 if (sh == 0) {
3033 tcg_gen_mov_tl(dst, src);
da91a00f 3034 tcg_gen_movi_tl(cpu_ca, 0);
af1c259f
SD
3035 if (is_isa300(ctx)) {
3036 tcg_gen_movi_tl(cpu_ca32, 0);
3037 }
26d67362 3038 } else {
ba4af3e4
RH
3039 TCGv t0;
3040 tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
3041 t0 = tcg_temp_new();
3042 tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1);
3043 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
3044 tcg_temp_free(t0);
3045 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
af1c259f
SD
3046 if (is_isa300(ctx)) {
3047 tcg_gen_mov_tl(cpu_ca32, cpu_ca);
3048 }
ba4af3e4
RH
3049 tcg_gen_sari_tl(dst, src, sh);
3050 }
3051 if (unlikely(Rc(ctx->opcode) != 0)) {
3052 gen_set_Rc0(ctx, dst);
d9bce9d9 3053 }
d9bce9d9 3054}
e8eaa2c0
BS
3055
3056static void gen_sradi0(DisasContext *ctx)
d9bce9d9
JM
3057{
3058 gen_sradi(ctx, 0);
3059}
e8eaa2c0
BS
3060
3061static void gen_sradi1(DisasContext *ctx)
d9bce9d9
JM
3062{
3063 gen_sradi(ctx, 1);
3064}
99e300ef 3065
787bbe37
ND
3066/* extswsli & extswsli. */
3067static inline void gen_extswsli(DisasContext *ctx, int n)
3068{
3069 int sh = SH(ctx->opcode) + (n << 5);
3070 TCGv dst = cpu_gpr[rA(ctx->opcode)];
3071 TCGv src = cpu_gpr[rS(ctx->opcode)];
3072
3073 tcg_gen_ext32s_tl(dst, src);
3074 tcg_gen_shli_tl(dst, dst, sh);
3075 if (unlikely(Rc(ctx->opcode) != 0)) {
3076 gen_set_Rc0(ctx, dst);
3077 }
3078}
3079
3080static void gen_extswsli0(DisasContext *ctx)
3081{
3082 gen_extswsli(ctx, 0);
3083}
3084
3085static void gen_extswsli1(DisasContext *ctx)
3086{
3087 gen_extswsli(ctx, 1);
3088}
3089
54623277 3090/* srd & srd. */
99e300ef 3091static void gen_srd(DisasContext *ctx)
26d67362 3092{
7fd6bf7d 3093 TCGv t0, t1;
26d67362 3094
7fd6bf7d
AJ
3095 t0 = tcg_temp_new();
3096 /* AND rS with a mask that is 0 when rB >= 0x40 */
3097 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
3098 tcg_gen_sari_tl(t0, t0, 0x3f);
3099 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
3100 t1 = tcg_temp_new();
3101 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
3102 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
3103 tcg_temp_free(t1);
fea0c503 3104 tcg_temp_free(t0);
efe843d8 3105 if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 3106 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
efe843d8 3107 }
26d67362 3108}
d9bce9d9 3109#endif
79aceca5 3110
76a66253
JM
3111/*** Addressing modes ***/
3112/* Register indirect with immediate index : EA = (rA|0) + SIMM */
636aa200
BS
3113static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
3114 target_long maskl)
76a66253
JM
3115{
3116 target_long simm = SIMM(ctx->opcode);
3117
be147d08 3118 simm &= ~maskl;
76db3ba4 3119 if (rA(ctx->opcode) == 0) {
c791fe84
RH
3120 if (NARROW_MODE(ctx)) {
3121 simm = (uint32_t)simm;
3122 }
e2be8d8d 3123 tcg_gen_movi_tl(EA, simm);
76db3ba4 3124 } else if (likely(simm != 0)) {
e2be8d8d 3125 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
c791fe84 3126 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
3127 tcg_gen_ext32u_tl(EA, EA);
3128 }
76db3ba4 3129 } else {
c791fe84 3130 if (NARROW_MODE(ctx)) {
76db3ba4 3131 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
c791fe84
RH
3132 } else {
3133 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
3134 }
76db3ba4 3135 }
76a66253
JM
3136}
3137
636aa200 3138static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
76a66253 3139{
76db3ba4 3140 if (rA(ctx->opcode) == 0) {
c791fe84 3141 if (NARROW_MODE(ctx)) {
76db3ba4 3142 tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
c791fe84
RH
3143 } else {
3144 tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
3145 }
76db3ba4 3146 } else {
e2be8d8d 3147 tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
c791fe84 3148 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
3149 tcg_gen_ext32u_tl(EA, EA);
3150 }
76db3ba4 3151 }
76a66253
JM
3152}
3153
636aa200 3154static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
76a66253 3155{
76db3ba4 3156 if (rA(ctx->opcode) == 0) {
e2be8d8d 3157 tcg_gen_movi_tl(EA, 0);
c791fe84
RH
3158 } else if (NARROW_MODE(ctx)) {
3159 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
76db3ba4 3160 } else {
c791fe84 3161 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
76db3ba4
AJ
3162 }
3163}
3164
636aa200
BS
3165static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
3166 target_long val)
76db3ba4
AJ
3167{
3168 tcg_gen_addi_tl(ret, arg1, val);
c791fe84 3169 if (NARROW_MODE(ctx)) {
76db3ba4
AJ
3170 tcg_gen_ext32u_tl(ret, ret);
3171 }
76a66253
JM
3172}
3173
65f2475f
BH
3174static inline void gen_align_no_le(DisasContext *ctx)
3175{
3176 gen_exception_err(ctx, POWERPC_EXCP_ALIGN,
3177 (ctx->opcode & 0x03FF0000) | POWERPC_EXCP_ALIGN_LE);
3178}
3179
eb63efd9
FEV
3180static TCGv do_ea_calc(DisasContext *ctx, int ra, TCGv displ)
3181{
3182 TCGv ea = tcg_temp_new();
3183 if (ra) {
3184 tcg_gen_add_tl(ea, cpu_gpr[ra], displ);
3185 } else {
3186 tcg_gen_mov_tl(ea, displ);
3187 }
3188 if (NARROW_MODE(ctx)) {
3189 tcg_gen_ext32u_tl(ea, ea);
3190 }
3191 return ea;
3192}
3193
7863667f 3194/*** Integer load ***/
09bfe50d 3195#define DEF_MEMOP(op) ((op) | ctx->default_tcg_memop_mask)
ff5f3981 3196#define BSWAP_MEMOP(op) ((op) | (ctx->default_tcg_memop_mask ^ MO_BSWAP))
b61f2753 3197
09bfe50d
ND
3198#define GEN_QEMU_LOAD_TL(ldop, op) \
3199static void glue(gen_qemu_, ldop)(DisasContext *ctx, \
3200 TCGv val, \
3201 TCGv addr) \
3202{ \
3203 tcg_gen_qemu_ld_tl(val, addr, ctx->mem_idx, op); \
b61f2753
AJ
3204}
3205
09bfe50d
ND
3206GEN_QEMU_LOAD_TL(ld8u, DEF_MEMOP(MO_UB))
3207GEN_QEMU_LOAD_TL(ld16u, DEF_MEMOP(MO_UW))
3208GEN_QEMU_LOAD_TL(ld16s, DEF_MEMOP(MO_SW))
3209GEN_QEMU_LOAD_TL(ld32u, DEF_MEMOP(MO_UL))
3210GEN_QEMU_LOAD_TL(ld32s, DEF_MEMOP(MO_SL))
f976b09e 3211
ff5f3981
ND
3212GEN_QEMU_LOAD_TL(ld16ur, BSWAP_MEMOP(MO_UW))
3213GEN_QEMU_LOAD_TL(ld32ur, BSWAP_MEMOP(MO_UL))
3214
09bfe50d
ND
3215#define GEN_QEMU_LOAD_64(ldop, op) \
3216static void glue(gen_qemu_, glue(ldop, _i64))(DisasContext *ctx, \
3217 TCGv_i64 val, \
3218 TCGv addr) \
3219{ \
3220 tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, op); \
b61f2753
AJ
3221}
3222
740ae9a2
ND
3223GEN_QEMU_LOAD_64(ld8u, DEF_MEMOP(MO_UB))
3224GEN_QEMU_LOAD_64(ld16u, DEF_MEMOP(MO_UW))
09bfe50d
ND
3225GEN_QEMU_LOAD_64(ld32u, DEF_MEMOP(MO_UL))
3226GEN_QEMU_LOAD_64(ld32s, DEF_MEMOP(MO_SL))
fc313c64 3227GEN_QEMU_LOAD_64(ld64, DEF_MEMOP(MO_UQ))
b61f2753 3228
ff5f3981 3229#if defined(TARGET_PPC64)
fc313c64 3230GEN_QEMU_LOAD_64(ld64ur, BSWAP_MEMOP(MO_UQ))
ff5f3981
ND
3231#endif
3232
761a89c6
ND
3233#define GEN_QEMU_STORE_TL(stop, op) \
3234static void glue(gen_qemu_, stop)(DisasContext *ctx, \
3235 TCGv val, \
3236 TCGv addr) \
3237{ \
3238 tcg_gen_qemu_st_tl(val, addr, ctx->mem_idx, op); \
b61f2753
AJ
3239}
3240
e8f4c8d6 3241#if defined(TARGET_PPC64) || !defined(CONFIG_USER_ONLY)
761a89c6 3242GEN_QEMU_STORE_TL(st8, DEF_MEMOP(MO_UB))
e8f4c8d6 3243#endif
761a89c6
ND
3244GEN_QEMU_STORE_TL(st16, DEF_MEMOP(MO_UW))
3245GEN_QEMU_STORE_TL(st32, DEF_MEMOP(MO_UL))
b61f2753 3246
804108aa
ND
3247GEN_QEMU_STORE_TL(st16r, BSWAP_MEMOP(MO_UW))
3248GEN_QEMU_STORE_TL(st32r, BSWAP_MEMOP(MO_UL))
3249
761a89c6
ND
3250#define GEN_QEMU_STORE_64(stop, op) \
3251static void glue(gen_qemu_, glue(stop, _i64))(DisasContext *ctx, \
3252 TCGv_i64 val, \
3253 TCGv addr) \
3254{ \
3255 tcg_gen_qemu_st_i64(val, addr, ctx->mem_idx, op); \
b61f2753
AJ
3256}
3257
ddb9ac50
ND
3258GEN_QEMU_STORE_64(st8, DEF_MEMOP(MO_UB))
3259GEN_QEMU_STORE_64(st16, DEF_MEMOP(MO_UW))
761a89c6 3260GEN_QEMU_STORE_64(st32, DEF_MEMOP(MO_UL))
fc313c64 3261GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_UQ))
b61f2753 3262
804108aa 3263#if defined(TARGET_PPC64)
fc313c64 3264GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_UQ))
804108aa
ND
3265#endif
3266
b7815375 3267#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk) \
99e300ef 3268static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 3269{ \
76db3ba4 3270 TCGv EA; \
9f0cf041 3271 chk(ctx); \
76db3ba4
AJ
3272 gen_set_access_type(ctx, ACCESS_INT); \
3273 EA = tcg_temp_new(); \
3274 gen_addr_reg_index(ctx, EA); \
3275 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753 3276 tcg_temp_free(EA); \
79aceca5 3277}
b7815375 3278
cd6e9320 3279#define GEN_LDX(name, ldop, opc2, opc3, type) \
b7815375
BH
3280 GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_NONE)
3281
3282#define GEN_LDX_HVRM(name, ldop, opc2, opc3, type) \
3283 GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_HVRM)
79aceca5 3284
50728199
RK
3285#define GEN_LDEPX(name, ldop, opc2, opc3) \
3286static void glue(gen_, name##epx)(DisasContext *ctx) \
3287{ \
3288 TCGv EA; \
9f0cf041 3289 CHK_SV(ctx); \
50728199
RK
3290 gen_set_access_type(ctx, ACCESS_INT); \
3291 EA = tcg_temp_new(); \
3292 gen_addr_reg_index(ctx, EA); \
3293 tcg_gen_qemu_ld_tl(cpu_gpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_LOAD, ldop);\
3294 tcg_temp_free(EA); \
3295}
3296
3297GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02)
3298GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08)
3299GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00)
3300#if defined(TARGET_PPC64)
fc313c64 3301GEN_LDEPX(ld, DEF_MEMOP(MO_UQ), 0x1D, 0x00)
50728199
RK
3302#endif
3303
d9bce9d9 3304#if defined(TARGET_PPC64)
b7815375 3305/* CI load/store variants */
4f364fe7 3306GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST)
b7815375
BH
3307GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x15, PPC_CILDST)
3308GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
3309GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
d9bce9d9 3310#endif
79aceca5
FB
3311
3312/*** Integer store ***/
b7815375 3313#define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk) \
cd6e9320 3314static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 3315{ \
76db3ba4 3316 TCGv EA; \
9f0cf041 3317 chk(ctx); \
76db3ba4
AJ
3318 gen_set_access_type(ctx, ACCESS_INT); \
3319 EA = tcg_temp_new(); \
3320 gen_addr_reg_index(ctx, EA); \
3321 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753 3322 tcg_temp_free(EA); \
79aceca5 3323}
cd6e9320 3324#define GEN_STX(name, stop, opc2, opc3, type) \
b7815375
BH
3325 GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_NONE)
3326
3327#define GEN_STX_HVRM(name, stop, opc2, opc3, type) \
3328 GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_HVRM)
79aceca5 3329
50728199
RK
3330#define GEN_STEPX(name, stop, opc2, opc3) \
3331static void glue(gen_, name##epx)(DisasContext *ctx) \
3332{ \
3333 TCGv EA; \
9f0cf041 3334 CHK_SV(ctx); \
50728199
RK
3335 gen_set_access_type(ctx, ACCESS_INT); \
3336 EA = tcg_temp_new(); \
3337 gen_addr_reg_index(ctx, EA); \
3338 tcg_gen_qemu_st_tl( \
3339 cpu_gpr[rD(ctx->opcode)], EA, PPC_TLB_EPID_STORE, stop); \
3340 tcg_temp_free(EA); \
3341}
3342
3343GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06)
3344GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C)
3345GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04)
3346#if defined(TARGET_PPC64)
fc313c64 3347GEN_STEPX(std, DEF_MEMOP(MO_UQ), 0x1d, 0x04)
50728199
RK
3348#endif
3349
d9bce9d9 3350#if defined(TARGET_PPC64)
2468f23d 3351GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST)
b7815375
BH
3352GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
3353GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
3354GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
d9bce9d9 3355#endif
79aceca5 3356/*** Integer load and store with byte reverse ***/
e22c357b 3357
79aceca5 3358/* lhbrx */
0c8aacd4 3359GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
b61f2753 3360
79aceca5 3361/* lwbrx */
0c8aacd4 3362GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
b61f2753 3363
cd6e9320
TH
3364#if defined(TARGET_PPC64)
3365/* ldbrx */
ff5f3981 3366GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE);
804108aa
ND
3367/* stdbrx */
3368GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE);
cd6e9320
TH
3369#endif /* TARGET_PPC64 */
3370
79aceca5 3371/* sthbrx */
0c8aacd4 3372GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
79aceca5 3373/* stwbrx */
0c8aacd4 3374GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
79aceca5
FB
3375
3376/*** Integer load and store multiple ***/
99e300ef 3377
54623277 3378/* lmw */
99e300ef 3379static void gen_lmw(DisasContext *ctx)
79aceca5 3380{
76db3ba4
AJ
3381 TCGv t0;
3382 TCGv_i32 t1;
5817355e
BH
3383
3384 if (ctx->le_mode) {
3385 gen_align_no_le(ctx);
3386 return;
3387 }
76db3ba4 3388 gen_set_access_type(ctx, ACCESS_INT);
76db3ba4
AJ
3389 t0 = tcg_temp_new();
3390 t1 = tcg_const_i32(rD(ctx->opcode));
3391 gen_addr_imm_index(ctx, t0, 0);
2f5a189c 3392 gen_helper_lmw(cpu_env, t0, t1);
ff4a62cd
AJ
3393 tcg_temp_free(t0);
3394 tcg_temp_free_i32(t1);
79aceca5
FB
3395}
3396
3397/* stmw */
99e300ef 3398static void gen_stmw(DisasContext *ctx)
79aceca5 3399{
76db3ba4
AJ
3400 TCGv t0;
3401 TCGv_i32 t1;
5817355e
BH
3402
3403 if (ctx->le_mode) {
3404 gen_align_no_le(ctx);
3405 return;
3406 }
76db3ba4 3407 gen_set_access_type(ctx, ACCESS_INT);
76db3ba4
AJ
3408 t0 = tcg_temp_new();
3409 t1 = tcg_const_i32(rS(ctx->opcode));
3410 gen_addr_imm_index(ctx, t0, 0);
2f5a189c 3411 gen_helper_stmw(cpu_env, t0, t1);
ff4a62cd
AJ
3412 tcg_temp_free(t0);
3413 tcg_temp_free_i32(t1);
79aceca5
FB
3414}
3415
3416/*** Integer load and store strings ***/
54623277 3417
79aceca5 3418/* lswi */
efe843d8
DG
3419/*
3420 * PowerPC32 specification says we must generate an exception if rA is
3421 * in the range of registers to be loaded. In an other hand, IBM says
3422 * this is valid, but rA won't be loaded. For now, I'll follow the
3423 * spec...
9a64fbe4 3424 */
99e300ef 3425static void gen_lswi(DisasContext *ctx)
79aceca5 3426{
dfbc799d
AJ
3427 TCGv t0;
3428 TCGv_i32 t1, t2;
79aceca5
FB
3429 int nb = NB(ctx->opcode);
3430 int start = rD(ctx->opcode);
9a64fbe4 3431 int ra = rA(ctx->opcode);
79aceca5
FB
3432 int nr;
3433
5817355e
BH
3434 if (ctx->le_mode) {
3435 gen_align_no_le(ctx);
3436 return;
3437 }
efe843d8 3438 if (nb == 0) {
79aceca5 3439 nb = 32;
efe843d8 3440 }
f0704d78 3441 nr = DIV_ROUND_UP(nb, 4);
afbee712 3442 if (unlikely(lsw_reg_in_range(start, nr, ra))) {
e06fcd75 3443 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
9fddaa0c 3444 return;
297d8e62 3445 }
76db3ba4 3446 gen_set_access_type(ctx, ACCESS_INT);
dfbc799d 3447 t0 = tcg_temp_new();
76db3ba4 3448 gen_addr_register(ctx, t0);
dfbc799d
AJ
3449 t1 = tcg_const_i32(nb);
3450 t2 = tcg_const_i32(start);
2f5a189c 3451 gen_helper_lsw(cpu_env, t0, t1, t2);
dfbc799d
AJ
3452 tcg_temp_free(t0);
3453 tcg_temp_free_i32(t1);
3454 tcg_temp_free_i32(t2);
79aceca5
FB
3455}
3456
3457/* lswx */
99e300ef 3458static void gen_lswx(DisasContext *ctx)
79aceca5 3459{
76db3ba4
AJ
3460 TCGv t0;
3461 TCGv_i32 t1, t2, t3;
5817355e
BH
3462
3463 if (ctx->le_mode) {
3464 gen_align_no_le(ctx);
3465 return;
3466 }
76db3ba4 3467 gen_set_access_type(ctx, ACCESS_INT);
76db3ba4
AJ
3468 t0 = tcg_temp_new();
3469 gen_addr_reg_index(ctx, t0);
3470 t1 = tcg_const_i32(rD(ctx->opcode));
3471 t2 = tcg_const_i32(rA(ctx->opcode));
3472 t3 = tcg_const_i32(rB(ctx->opcode));
2f5a189c 3473 gen_helper_lswx(cpu_env, t0, t1, t2, t3);
dfbc799d
AJ
3474 tcg_temp_free(t0);
3475 tcg_temp_free_i32(t1);
3476 tcg_temp_free_i32(t2);
3477 tcg_temp_free_i32(t3);
79aceca5
FB
3478}
3479
3480/* stswi */
99e300ef 3481static void gen_stswi(DisasContext *ctx)
79aceca5 3482{
76db3ba4
AJ
3483 TCGv t0;
3484 TCGv_i32 t1, t2;
4b3686fa 3485 int nb = NB(ctx->opcode);
5817355e
BH
3486
3487 if (ctx->le_mode) {
3488 gen_align_no_le(ctx);
3489 return;
3490 }
76db3ba4 3491 gen_set_access_type(ctx, ACCESS_INT);
76db3ba4
AJ
3492 t0 = tcg_temp_new();
3493 gen_addr_register(ctx, t0);
efe843d8 3494 if (nb == 0) {
4b3686fa 3495 nb = 32;
efe843d8 3496 }
dfbc799d 3497 t1 = tcg_const_i32(nb);
76db3ba4 3498 t2 = tcg_const_i32(rS(ctx->opcode));
2f5a189c 3499 gen_helper_stsw(cpu_env, t0, t1, t2);
dfbc799d
AJ
3500 tcg_temp_free(t0);
3501 tcg_temp_free_i32(t1);
3502 tcg_temp_free_i32(t2);
79aceca5
FB
3503}
3504
3505/* stswx */
99e300ef 3506static void gen_stswx(DisasContext *ctx)
79aceca5 3507{
76db3ba4
AJ
3508 TCGv t0;
3509 TCGv_i32 t1, t2;
5817355e
BH
3510
3511 if (ctx->le_mode) {
3512 gen_align_no_le(ctx);
3513 return;
3514 }
76db3ba4 3515 gen_set_access_type(ctx, ACCESS_INT);
76db3ba4
AJ
3516 t0 = tcg_temp_new();
3517 gen_addr_reg_index(ctx, t0);
3518 t1 = tcg_temp_new_i32();
dfbc799d
AJ
3519 tcg_gen_trunc_tl_i32(t1, cpu_xer);
3520 tcg_gen_andi_i32(t1, t1, 0x7F);
76db3ba4 3521 t2 = tcg_const_i32(rS(ctx->opcode));
2f5a189c 3522 gen_helper_stsw(cpu_env, t0, t1, t2);
dfbc799d
AJ
3523 tcg_temp_free(t0);
3524 tcg_temp_free_i32(t1);
3525 tcg_temp_free_i32(t2);
79aceca5
FB
3526}
3527
3528/*** Memory synchronisation ***/
3529/* eieio */
99e300ef 3530static void gen_eieio(DisasContext *ctx)
79aceca5 3531{
fcb830af
NP
3532 TCGBar bar = TCG_MO_ALL;
3533
3534 /*
3535 * eieio has complex semanitcs. It provides memory ordering between
3536 * operations in the set:
3537 * - loads from CI memory.
3538 * - stores to CI memory.
3539 * - stores to WT memory.
3540 *
3541 * It separately also orders memory for operations in the set:
3542 * - stores to cacheble memory.
3543 *
3544 * It also serializes instructions:
3545 * - dcbt and dcbst.
3546 *
3547 * It separately serializes:
3548 * - tlbie and tlbsync.
3549 *
3550 * And separately serializes:
3551 * - slbieg, slbiag, and slbsync.
3552 *
3553 * The end result is that CI memory ordering requires TCG_MO_ALL
3554 * and it is not possible to special-case more relaxed ordering for
3555 * cacheable accesses. TCG_BAR_SC is required to provide this
3556 * serialization.
3557 */
c8fd8373
CLG
3558
3559 /*
3560 * POWER9 has a eieio instruction variant using bit 6 as a hint to
3561 * tell the CPU it is a store-forwarding barrier.
3562 */
3563 if (ctx->opcode & 0x2000000) {
3564 /*
3565 * ISA says that "Reserved fields in instructions are ignored
3566 * by the processor". So ignore the bit 6 on non-POWER9 CPU but
3567 * as this is not an instruction software should be using,
3568 * complain to the user.
3569 */
3570 if (!(ctx->insns_flags2 & PPC2_ISA300)) {
3571 qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
2c2bcb1b 3572 TARGET_FMT_lx "\n", ctx->cia);
c8fd8373
CLG
3573 } else {
3574 bar = TCG_MO_ST_LD;
3575 }
3576 }
3577
3578 tcg_gen_mb(bar | TCG_BAR_SC);
79aceca5
FB
3579}
3580
c5a8d8f3 3581#if !defined(CONFIG_USER_ONLY)
e3cffe6f 3582static inline void gen_check_tlb_flush(DisasContext *ctx, bool global)
cd0c6f47 3583{
c5a8d8f3
BH
3584 TCGv_i32 t;
3585 TCGLabel *l;
cd0c6f47 3586
c5a8d8f3
BH
3587 if (!ctx->lazy_tlb_flush) {
3588 return;
3589 }
3590 l = gen_new_label();
3591 t = tcg_temp_new_i32();
cd0c6f47
BH
3592 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
3593 tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, l);
e3cffe6f
ND
3594 if (global) {
3595 gen_helper_check_tlb_flush_global(cpu_env);
3596 } else {
3597 gen_helper_check_tlb_flush_local(cpu_env);
3598 }
cd0c6f47
BH
3599 gen_set_label(l);
3600 tcg_temp_free_i32(t);
3601}
3602#else
e3cffe6f 3603static inline void gen_check_tlb_flush(DisasContext *ctx, bool global) { }
cd0c6f47
BH
3604#endif
3605
79aceca5 3606/* isync */
99e300ef 3607static void gen_isync(DisasContext *ctx)
79aceca5 3608{
cd0c6f47
BH
3609 /*
3610 * We need to check for a pending TLB flush. This can only happen in
3611 * kernel mode however so check MSR_PR
3612 */
3613 if (!ctx->pr) {
e3cffe6f 3614 gen_check_tlb_flush(ctx, false);
cd0c6f47 3615 }
4771df23 3616 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
d736de8f 3617 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
79aceca5
FB
3618}
3619
48793c95
ND
3620#define MEMOP_GET_SIZE(x) (1 << ((x) & MO_SIZE))
3621
14776ab5 3622static void gen_load_locked(DisasContext *ctx, MemOp memop)
2a4e6c1b
RH
3623{
3624 TCGv gpr = cpu_gpr[rD(ctx->opcode)];
3625 TCGv t0 = tcg_temp_new();
3626
3627 gen_set_access_type(ctx, ACCESS_RES);
3628 gen_addr_reg_index(ctx, t0);
3629 tcg_gen_qemu_ld_tl(gpr, t0, ctx->mem_idx, memop | MO_ALIGN);
3630 tcg_gen_mov_tl(cpu_reserve, t0);
3631 tcg_gen_mov_tl(cpu_reserve_val, gpr);
3632 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
3633 tcg_temp_free(t0);
3634}
3635
3636#define LARX(name, memop) \
3637static void gen_##name(DisasContext *ctx) \
3638{ \
3639 gen_load_locked(ctx, memop); \
79aceca5
FB
3640}
3641
5c77a786 3642/* lwarx */
48793c95
ND
3643LARX(lbarx, DEF_MEMOP(MO_UB))
3644LARX(lharx, DEF_MEMOP(MO_UW))
3645LARX(lwarx, DEF_MEMOP(MO_UL))
5c77a786 3646
14776ab5 3647static void gen_fetch_inc_conditional(DisasContext *ctx, MemOp memop,
20923c1d
RH
3648 TCGv EA, TCGCond cond, int addend)
3649{
3650 TCGv t = tcg_temp_new();
3651 TCGv t2 = tcg_temp_new();
3652 TCGv u = tcg_temp_new();
3653
3654 tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
3655 tcg_gen_addi_tl(t2, EA, MEMOP_GET_SIZE(memop));
3656 tcg_gen_qemu_ld_tl(t2, t2, ctx->mem_idx, memop);
3657 tcg_gen_addi_tl(u, t, addend);
3658
3659 /* E.g. for fetch and increment bounded... */
3660 /* mem(EA,s) = (t != t2 ? u = t + 1 : t) */
3661 tcg_gen_movcond_tl(cond, u, t, t2, u, t);
3662 tcg_gen_qemu_st_tl(u, EA, ctx->mem_idx, memop);
3663
3664 /* RT = (t != t2 ? t : u = 1<<(s*8-1)) */
3665 tcg_gen_movi_tl(u, 1 << (MEMOP_GET_SIZE(memop) * 8 - 1));
3666 tcg_gen_movcond_tl(cond, cpu_gpr[rD(ctx->opcode)], t, t2, t, u);
3667
3668 tcg_temp_free(t);
3669 tcg_temp_free(t2);
3670 tcg_temp_free(u);
3671}
3672
14776ab5 3673static void gen_ld_atomic(DisasContext *ctx, MemOp memop)
20ba8504
RH
3674{
3675 uint32_t gpr_FC = FC(ctx->opcode);
3676 TCGv EA = tcg_temp_new();
20923c1d
RH
3677 int rt = rD(ctx->opcode);
3678 bool need_serial;
20ba8504
RH
3679 TCGv src, dst;
3680
3681 gen_addr_register(ctx, EA);
20923c1d
RH
3682 dst = cpu_gpr[rt];
3683 src = cpu_gpr[(rt + 1) & 31];
20ba8504 3684
20923c1d 3685 need_serial = false;
20ba8504
RH
3686 memop |= MO_ALIGN;
3687 switch (gpr_FC) {
3688 case 0: /* Fetch and add */
3689 tcg_gen_atomic_fetch_add_tl(dst, EA, src, ctx->mem_idx, memop);
3690 break;
3691 case 1: /* Fetch and xor */
3692 tcg_gen_atomic_fetch_xor_tl(dst, EA, src, ctx->mem_idx, memop);
3693 break;
3694 case 2: /* Fetch and or */
3695 tcg_gen_atomic_fetch_or_tl(dst, EA, src, ctx->mem_idx, memop);
3696 break;
3697 case 3: /* Fetch and 'and' */
3698 tcg_gen_atomic_fetch_and_tl(dst, EA, src, ctx->mem_idx, memop);
3699 break;
20ba8504 3700 case 4: /* Fetch and max unsigned */
b8ce0f86
RH
3701 tcg_gen_atomic_fetch_umax_tl(dst, EA, src, ctx->mem_idx, memop);
3702 break;
20ba8504 3703 case 5: /* Fetch and max signed */
b8ce0f86
RH
3704 tcg_gen_atomic_fetch_smax_tl(dst, EA, src, ctx->mem_idx, memop);
3705 break;
20ba8504 3706 case 6: /* Fetch and min unsigned */
b8ce0f86
RH
3707 tcg_gen_atomic_fetch_umin_tl(dst, EA, src, ctx->mem_idx, memop);
3708 break;
20ba8504 3709 case 7: /* Fetch and min signed */
b8ce0f86
RH
3710 tcg_gen_atomic_fetch_smin_tl(dst, EA, src, ctx->mem_idx, memop);
3711 break;
3712 case 8: /* Swap */
3713 tcg_gen_atomic_xchg_tl(dst, EA, src, ctx->mem_idx, memop);
3714 break;
20923c1d
RH
3715
3716 case 16: /* Compare and swap not equal */
3717 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3718 need_serial = true;
3719 } else {
3720 TCGv t0 = tcg_temp_new();
3721 TCGv t1 = tcg_temp_new();
3722
3723 tcg_gen_qemu_ld_tl(t0, EA, ctx->mem_idx, memop);
3724 if ((memop & MO_SIZE) == MO_64 || TARGET_LONG_BITS == 32) {
3725 tcg_gen_mov_tl(t1, src);
3726 } else {
3727 tcg_gen_ext32u_tl(t1, src);
3728 }
3729 tcg_gen_movcond_tl(TCG_COND_NE, t1, t0, t1,
3730 cpu_gpr[(rt + 2) & 31], t0);
3731 tcg_gen_qemu_st_tl(t1, EA, ctx->mem_idx, memop);
3732 tcg_gen_mov_tl(dst, t0);
3733
3734 tcg_temp_free(t0);
3735 tcg_temp_free(t1);
3736 }
3737 break;
3738
20ba8504 3739 case 24: /* Fetch and increment bounded */
20923c1d
RH
3740 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3741 need_serial = true;
3742 } else {
3743 gen_fetch_inc_conditional(ctx, memop, EA, TCG_COND_NE, 1);
3744 }
3745 break;
20ba8504 3746 case 25: /* Fetch and increment equal */
20923c1d
RH
3747 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3748 need_serial = true;
3749 } else {
3750 gen_fetch_inc_conditional(ctx, memop, EA, TCG_COND_EQ, 1);
3751 }
3752 break;
20ba8504 3753 case 28: /* Fetch and decrement bounded */
20923c1d
RH
3754 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3755 need_serial = true;
3756 } else {
3757 gen_fetch_inc_conditional(ctx, memop, EA, TCG_COND_NE, -1);
3758 }
20ba8504 3759 break;
20923c1d 3760
20ba8504
RH
3761 default:
3762 /* invoke data storage error handler */
3763 gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
3764 }
3765 tcg_temp_free(EA);
20923c1d
RH
3766
3767 if (need_serial) {
3768 /* Restart with exclusive lock. */
3769 gen_helper_exit_atomic(cpu_env);
3770 ctx->base.is_jmp = DISAS_NORETURN;
3771 }
20ba8504
RH
3772}
3773
3774static void gen_lwat(DisasContext *ctx)
3775{
3776 gen_ld_atomic(ctx, DEF_MEMOP(MO_UL));
3777}
3778
3779#ifdef TARGET_PPC64
3780static void gen_ldat(DisasContext *ctx)
3781{
fc313c64 3782 gen_ld_atomic(ctx, DEF_MEMOP(MO_UQ));
20ba8504 3783}
a68a6146
B
3784#endif
3785
14776ab5 3786static void gen_st_atomic(DisasContext *ctx, MemOp memop)
9deb041c
RH
3787{
3788 uint32_t gpr_FC = FC(ctx->opcode);
3789 TCGv EA = tcg_temp_new();
3790 TCGv src, discard;
3791
3792 gen_addr_register(ctx, EA);
3793 src = cpu_gpr[rD(ctx->opcode)];
3794 discard = tcg_temp_new();
3795
3796 memop |= MO_ALIGN;
3797 switch (gpr_FC) {
3798 case 0: /* add and Store */
3799 tcg_gen_atomic_add_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3800 break;
3801 case 1: /* xor and Store */
3802 tcg_gen_atomic_xor_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3803 break;
3804 case 2: /* Or and Store */
3805 tcg_gen_atomic_or_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3806 break;
3807 case 3: /* 'and' and Store */
3808 tcg_gen_atomic_and_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3809 break;
3810 case 4: /* Store max unsigned */
b8ce0f86
RH
3811 tcg_gen_atomic_umax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3812 break;
9deb041c 3813 case 5: /* Store max signed */
b8ce0f86
RH
3814 tcg_gen_atomic_smax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3815 break;
9deb041c 3816 case 6: /* Store min unsigned */
b8ce0f86
RH
3817 tcg_gen_atomic_umin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3818 break;
9deb041c 3819 case 7: /* Store min signed */
b8ce0f86
RH
3820 tcg_gen_atomic_smin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
3821 break;
9deb041c 3822 case 24: /* Store twin */
7fbc2b20
RH
3823 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3824 /* Restart with exclusive lock. */
3825 gen_helper_exit_atomic(cpu_env);
3826 ctx->base.is_jmp = DISAS_NORETURN;
3827 } else {
3828 TCGv t = tcg_temp_new();
3829 TCGv t2 = tcg_temp_new();
3830 TCGv s = tcg_temp_new();
3831 TCGv s2 = tcg_temp_new();
3832 TCGv ea_plus_s = tcg_temp_new();
3833
3834 tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
3835 tcg_gen_addi_tl(ea_plus_s, EA, MEMOP_GET_SIZE(memop));
3836 tcg_gen_qemu_ld_tl(t2, ea_plus_s, ctx->mem_idx, memop);
3837 tcg_gen_movcond_tl(TCG_COND_EQ, s, t, t2, src, t);
3838 tcg_gen_movcond_tl(TCG_COND_EQ, s2, t, t2, src, t2);
3839 tcg_gen_qemu_st_tl(s, EA, ctx->mem_idx, memop);
3840 tcg_gen_qemu_st_tl(s2, ea_plus_s, ctx->mem_idx, memop);
3841
3842 tcg_temp_free(ea_plus_s);
3843 tcg_temp_free(s2);
3844 tcg_temp_free(s);
3845 tcg_temp_free(t2);
3846 tcg_temp_free(t);
3847 }
9deb041c
RH
3848 break;
3849 default:
3850 /* invoke data storage error handler */
3851 gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
3852 }
3853 tcg_temp_free(discard);
3854 tcg_temp_free(EA);
3855}
3856
3857static void gen_stwat(DisasContext *ctx)
3858{
3859 gen_st_atomic(ctx, DEF_MEMOP(MO_UL));
3860}
3861
3862#ifdef TARGET_PPC64
3863static void gen_stdat(DisasContext *ctx)
3864{
fc313c64 3865 gen_st_atomic(ctx, DEF_MEMOP(MO_UQ));
9deb041c 3866}
a3401188
B
3867#endif
3868
14776ab5 3869static void gen_conditional_store(DisasContext *ctx, MemOp memop)
587c51f7 3870{
253ce7b2
ND
3871 TCGLabel *l1 = gen_new_label();
3872 TCGLabel *l2 = gen_new_label();
d8b86898
RH
3873 TCGv t0 = tcg_temp_new();
3874 int reg = rS(ctx->opcode);
4425265b 3875
d8b86898
RH
3876 gen_set_access_type(ctx, ACCESS_RES);
3877 gen_addr_reg_index(ctx, t0);
3878 tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3879 tcg_temp_free(t0);
253ce7b2
ND
3880
3881 t0 = tcg_temp_new();
3882 tcg_gen_atomic_cmpxchg_tl(t0, cpu_reserve, cpu_reserve_val,
3883 cpu_gpr[reg], ctx->mem_idx,
3884 DEF_MEMOP(memop) | MO_ALIGN);
3885 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_reserve_val);
3886 tcg_gen_shli_tl(t0, t0, CRF_EQ_BIT);
3887 tcg_gen_or_tl(t0, t0, cpu_so);
3888 tcg_gen_trunc_tl_i32(cpu_crf[0], t0);
3889 tcg_temp_free(t0);
3890 tcg_gen_br(l2);
3891
587c51f7 3892 gen_set_label(l1);
4771df23 3893
efe843d8
DG
3894 /*
3895 * Address mismatch implies failure. But we still need to provide
3896 * the memory barrier semantics of the instruction.
3897 */
4771df23 3898 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
253ce7b2
ND
3899 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
3900
3901 gen_set_label(l2);
587c51f7
TM
3902 tcg_gen_movi_tl(cpu_reserve, -1);
3903}
587c51f7 3904
d8b86898
RH
3905#define STCX(name, memop) \
3906static void gen_##name(DisasContext *ctx) \
3907{ \
3908 gen_conditional_store(ctx, memop); \
2391b357
ND
3909}
3910
3911STCX(stbcx_, DEF_MEMOP(MO_UB))
3912STCX(sthcx_, DEF_MEMOP(MO_UW))
3913STCX(stwcx_, DEF_MEMOP(MO_UL))
587c51f7 3914
426613db 3915#if defined(TARGET_PPC64)
426613db 3916/* ldarx */
fc313c64 3917LARX(ldarx, DEF_MEMOP(MO_UQ))
2391b357 3918/* stdcx. */
fc313c64 3919STCX(stdcx_, DEF_MEMOP(MO_UQ))
426613db 3920
9c294d5a
TM
3921/* lqarx */
3922static void gen_lqarx(DisasContext *ctx)
3923{
9c294d5a 3924 int rd = rD(ctx->opcode);
94bf2658 3925 TCGv EA, hi, lo;
9c294d5a
TM
3926
3927 if (unlikely((rd & 1) || (rd == rA(ctx->opcode)) ||
3928 (rd == rB(ctx->opcode)))) {
3929 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3930 return;
3931 }
3932
3933 gen_set_access_type(ctx, ACCESS_RES);
94bf2658 3934 EA = tcg_temp_new();
9c294d5a 3935 gen_addr_reg_index(ctx, EA);
94bf2658
RH
3936
3937 /* Note that the low part is always in RD+1, even in LE mode. */
3938 lo = cpu_gpr[rd + 1];
3939 hi = cpu_gpr[rd];
3940
3941 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
f34ec0f6
RH
3942 if (HAVE_ATOMIC128) {
3943 TCGv_i32 oi = tcg_temp_new_i32();
3944 if (ctx->le_mode) {
68e33d86 3945 tcg_gen_movi_i32(oi, make_memop_idx(MO_LE | MO_128 | MO_ALIGN,
f34ec0f6
RH
3946 ctx->mem_idx));
3947 gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
3948 } else {
68e33d86 3949 tcg_gen_movi_i32(oi, make_memop_idx(MO_BE | MO_128 | MO_ALIGN,
f34ec0f6
RH
3950 ctx->mem_idx));
3951 gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
3952 }
3953 tcg_temp_free_i32(oi);
3954 tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
94bf2658 3955 } else {
f34ec0f6
RH
3956 /* Restart with exclusive lock. */
3957 gen_helper_exit_atomic(cpu_env);
3958 ctx->base.is_jmp = DISAS_NORETURN;
3959 tcg_temp_free(EA);
3960 return;
94bf2658 3961 }
94bf2658 3962 } else if (ctx->le_mode) {
fc313c64 3963 tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEUQ | MO_ALIGN_16);
94bf2658
RH
3964 tcg_gen_mov_tl(cpu_reserve, EA);
3965 gen_addr_add(ctx, EA, EA, 8);
fc313c64 3966 tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_LEUQ);
9c294d5a 3967 } else {
fc313c64 3968 tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_BEUQ | MO_ALIGN_16);
94bf2658
RH
3969 tcg_gen_mov_tl(cpu_reserve, EA);
3970 gen_addr_add(ctx, EA, EA, 8);
fc313c64 3971 tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_BEUQ);
9c294d5a 3972 }
9c294d5a 3973 tcg_temp_free(EA);
94bf2658
RH
3974
3975 tcg_gen_st_tl(hi, cpu_env, offsetof(CPUPPCState, reserve_val));
3976 tcg_gen_st_tl(lo, cpu_env, offsetof(CPUPPCState, reserve_val2));
9c294d5a
TM
3977}
3978
aa2008af
ND
3979/* stqcx. */
3980static void gen_stqcx_(DisasContext *ctx)
3981{
4a9b3c5d
RH
3982 int rs = rS(ctx->opcode);
3983 TCGv EA, hi, lo;
aa2008af 3984
4a9b3c5d 3985 if (unlikely(rs & 1)) {
aa2008af
ND
3986 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
3987 return;
3988 }
4a9b3c5d 3989
aa2008af 3990 gen_set_access_type(ctx, ACCESS_RES);
4a9b3c5d 3991 EA = tcg_temp_new();
aa2008af 3992 gen_addr_reg_index(ctx, EA);
aa2008af 3993
4a9b3c5d
RH
3994 /* Note that the low part is always in RS+1, even in LE mode. */
3995 lo = cpu_gpr[rs + 1];
3996 hi = cpu_gpr[rs];
aa2008af 3997
4a9b3c5d 3998 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
f34ec0f6 3999 if (HAVE_CMPXCHG128) {
68e33d86 4000 TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_128) | MO_ALIGN);
f34ec0f6
RH
4001 if (ctx->le_mode) {
4002 gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env,
4003 EA, lo, hi, oi);
4004 } else {
4005 gen_helper_stqcx_be_parallel(cpu_crf[0], cpu_env,
4006 EA, lo, hi, oi);
4007 }
4008 tcg_temp_free_i32(oi);
4a9b3c5d 4009 } else {
f34ec0f6
RH
4010 /* Restart with exclusive lock. */
4011 gen_helper_exit_atomic(cpu_env);
4012 ctx->base.is_jmp = DISAS_NORETURN;
4a9b3c5d 4013 }
4a9b3c5d 4014 tcg_temp_free(EA);
aa2008af 4015 } else {
4a9b3c5d
RH
4016 TCGLabel *lab_fail = gen_new_label();
4017 TCGLabel *lab_over = gen_new_label();
4018 TCGv_i64 t0 = tcg_temp_new_i64();
4019 TCGv_i64 t1 = tcg_temp_new_i64();
aa2008af 4020
4a9b3c5d
RH
4021 tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, lab_fail);
4022 tcg_temp_free(EA);
aa2008af 4023
4a9b3c5d
RH
4024 gen_qemu_ld64_i64(ctx, t0, cpu_reserve);
4025 tcg_gen_ld_i64(t1, cpu_env, (ctx->le_mode
4026 ? offsetof(CPUPPCState, reserve_val2)
4027 : offsetof(CPUPPCState, reserve_val)));
4028 tcg_gen_brcond_i64(TCG_COND_NE, t0, t1, lab_fail);
4029
4030 tcg_gen_addi_i64(t0, cpu_reserve, 8);
4031 gen_qemu_ld64_i64(ctx, t0, t0);
4032 tcg_gen_ld_i64(t1, cpu_env, (ctx->le_mode
4033 ? offsetof(CPUPPCState, reserve_val)
4034 : offsetof(CPUPPCState, reserve_val2)));
4035 tcg_gen_brcond_i64(TCG_COND_NE, t0, t1, lab_fail);
4036
4037 /* Success */
4038 gen_qemu_st64_i64(ctx, ctx->le_mode ? lo : hi, cpu_reserve);
4039 tcg_gen_addi_i64(t0, cpu_reserve, 8);
4040 gen_qemu_st64_i64(ctx, ctx->le_mode ? hi : lo, t0);
4041
4042 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
4043 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], CRF_EQ);
4044 tcg_gen_br(lab_over);
4045
4046 gen_set_label(lab_fail);
4047 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
4048
4049 gen_set_label(lab_over);
4050 tcg_gen_movi_tl(cpu_reserve, -1);
4051 tcg_temp_free_i64(t0);
4052 tcg_temp_free_i64(t1);
4053 }
4054}
426613db
JM
4055#endif /* defined(TARGET_PPC64) */
4056
79aceca5 4057/* sync */
99e300ef 4058static void gen_sync(DisasContext *ctx)
79aceca5 4059{
03abfd90 4060 TCGBar bar = TCG_MO_ALL;
cd0c6f47
BH
4061 uint32_t l = (ctx->opcode >> 21) & 3;
4062
03abfd90
NP
4063 if ((l == 1) && (ctx->insns_flags2 & PPC2_MEM_LWSYNC)) {
4064 bar = TCG_MO_LD_LD | TCG_MO_LD_ST | TCG_MO_ST_ST;
4065 }
4066
cd0c6f47 4067 /*
c5a8d8f3
BH
4068 * We may need to check for a pending TLB flush.
4069 *
4070 * We do this on ptesync (l == 2) on ppc64 and any sync pn ppc32.
4071 *
4072 * Additionally, this can only happen in kernel mode however so
4073 * check MSR_PR as well.
cd0c6f47 4074 */
c5a8d8f3 4075 if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
e3cffe6f 4076 gen_check_tlb_flush(ctx, true);
cd0c6f47 4077 }
03abfd90
NP
4078
4079 tcg_gen_mb(bar | TCG_BAR_SC);
79aceca5
FB
4080}
4081
0db1b20e 4082/* wait */
99e300ef 4083static void gen_wait(DisasContext *ctx)
0db1b20e 4084{
0c9717ff
NP
4085 uint32_t wc;
4086
4087 if (ctx->insns_flags & PPC_WAIT) {
4088 /* v2.03-v2.07 define an older incompatible 'wait' encoding. */
4089
4090 if (ctx->insns_flags2 & PPC2_PM_ISA206) {
4091 /* v2.06 introduced the WC field. WC > 0 may be treated as no-op. */
4092 wc = WC(ctx->opcode);
4093 } else {
4094 wc = 0;
4095 }
4096
4097 } else if (ctx->insns_flags2 & PPC2_ISA300) {
4098 /* v3.0 defines a new 'wait' encoding. */
4099 wc = WC(ctx->opcode);
4100 if (ctx->insns_flags2 & PPC2_ISA310) {
4101 uint32_t pl = PL(ctx->opcode);
4102
4103 /* WC 1,2 may be treated as no-op. WC 3 is reserved. */
4104 if (wc == 3) {
4105 gen_invalid(ctx);
4106 return;
4107 }
4108
4109 /* PL 1-3 are reserved. If WC=2 then the insn is treated as noop. */
4110 if (pl > 0 && wc != 2) {
4111 gen_invalid(ctx);
4112 return;
4113 }
4114
4115 } else { /* ISA300 */
4116 /* WC 1-3 are reserved */
4117 if (wc > 0) {
4118 gen_invalid(ctx);
4119 return;
4120 }
4121 }
4122
4123 } else {
4124 warn_report("wait instruction decoded with wrong ISA flags.");
4125 gen_invalid(ctx);
4126 return;
4127 }
4128
4129 /*
4130 * wait without WC field or with WC=0 waits for an exception / interrupt
4131 * to occur.
4132 */
4133 if (wc == 0) {
4134 TCGv_i32 t0 = tcg_const_i32(1);
4135 tcg_gen_st_i32(t0, cpu_env,
4136 -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
4137 tcg_temp_free_i32(t0);
4138 /* Stop translation, as the CPU is supposed to sleep from now */
4139 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
4140 }
4141
4142 /*
4143 * Other wait types must not just wait until an exception occurs because
4144 * ignoring their other wake-up conditions could cause a hang.
4145 *
4146 * For v2.06 and 2.07, wc=1,2,3 are architected but may be implemented as
4147 * no-ops.
4148 *
4149 * wc=1 and wc=3 explicitly allow the instruction to be treated as a no-op.
4150 *
4151 * wc=2 waits for an implementation-specific condition, such could be
4152 * always true, so it can be implemented as a no-op.
4153 *
4154 * For v3.1, wc=1,2 are architected but may be implemented as no-ops.
4155 *
4156 * wc=1 (waitrsv) waits for an exception or a reservation to be lost.
4157 * Reservation-loss may have implementation-specific conditions, so it
4158 * can be implemented as a no-op.
4159 *
4160 * wc=2 waits for an exception or an amount of time to pass. This
4161 * amount is implementation-specific so it can be implemented as a
4162 * no-op.
4163 *
4164 * ISA v3.1 allows for execution to resume "in the rare case of
4165 * an implementation-dependent event", so in any case software must
4166 * not depend on the architected resumption condition to become
4167 * true, so no-op implementations should be architecturally correct
4168 * (if suboptimal).
4169 */
0db1b20e
JM
4170}
4171
7778a575
BH
4172#if defined(TARGET_PPC64)
4173static void gen_doze(DisasContext *ctx)
4174{
4175#if defined(CONFIG_USER_ONLY)
9f0cf041 4176 GEN_PRIV(ctx);
7778a575
BH
4177#else
4178 TCGv_i32 t;
4179
9f0cf041 4180 CHK_HV(ctx);
7778a575
BH
4181 t = tcg_const_i32(PPC_PM_DOZE);
4182 gen_helper_pminsn(cpu_env, t);
4183 tcg_temp_free_i32(t);
154c69f2
BH
4184 /* Stop translation, as the CPU is supposed to sleep from now */
4185 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
7778a575
BH
4186#endif /* defined(CONFIG_USER_ONLY) */
4187}
4188
4189static void gen_nap(DisasContext *ctx)
4190{
4191#if defined(CONFIG_USER_ONLY)
9f0cf041 4192 GEN_PRIV(ctx);
7778a575
BH
4193#else
4194 TCGv_i32 t;
4195
9f0cf041 4196 CHK_HV(ctx);
7778a575
BH
4197 t = tcg_const_i32(PPC_PM_NAP);
4198 gen_helper_pminsn(cpu_env, t);
4199 tcg_temp_free_i32(t);
154c69f2
BH
4200 /* Stop translation, as the CPU is supposed to sleep from now */
4201 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
7778a575
BH
4202#endif /* defined(CONFIG_USER_ONLY) */
4203}
4204
cdee0e72
ND
4205static void gen_stop(DisasContext *ctx)
4206{
21c0d66a 4207#if defined(CONFIG_USER_ONLY)
9f0cf041 4208 GEN_PRIV(ctx);
21c0d66a
BH
4209#else
4210 TCGv_i32 t;
4211
9f0cf041 4212 CHK_HV(ctx);
21c0d66a
BH
4213 t = tcg_const_i32(PPC_PM_STOP);
4214 gen_helper_pminsn(cpu_env, t);
4215 tcg_temp_free_i32(t);
4216 /* Stop translation, as the CPU is supposed to sleep from now */
4217 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
4218#endif /* defined(CONFIG_USER_ONLY) */
cdee0e72
ND
4219}
4220
7778a575
BH
4221static void gen_sleep(DisasContext *ctx)
4222{
4223#if defined(CONFIG_USER_ONLY)
9f0cf041 4224 GEN_PRIV(ctx);
7778a575
BH
4225#else
4226 TCGv_i32 t;
4227
9f0cf041 4228 CHK_HV(ctx);
7778a575
BH
4229 t = tcg_const_i32(PPC_PM_SLEEP);
4230 gen_helper_pminsn(cpu_env, t);
4231 tcg_temp_free_i32(t);
154c69f2
BH
4232 /* Stop translation, as the CPU is supposed to sleep from now */
4233 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
7778a575
BH
4234#endif /* defined(CONFIG_USER_ONLY) */
4235}
4236
4237static void gen_rvwinkle(DisasContext *ctx)
4238{
4239#if defined(CONFIG_USER_ONLY)
9f0cf041 4240 GEN_PRIV(ctx);
7778a575
BH
4241#else
4242 TCGv_i32 t;
4243
9f0cf041 4244 CHK_HV(ctx);
7778a575
BH
4245 t = tcg_const_i32(PPC_PM_RVWINKLE);
4246 gen_helper_pminsn(cpu_env, t);
4247 tcg_temp_free_i32(t);
154c69f2
BH
4248 /* Stop translation, as the CPU is supposed to sleep from now */
4249 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
7778a575
BH
4250#endif /* defined(CONFIG_USER_ONLY) */
4251}
4252#endif /* #if defined(TARGET_PPC64) */
4253
697ab892
DG
4254static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
4255{
4256#if defined(TARGET_PPC64)
efe843d8 4257 if (ctx->has_cfar) {
697ab892 4258 tcg_gen_movi_tl(cpu_cfar, nip);
efe843d8 4259 }
697ab892
DG
4260#endif
4261}
4262
46d396bd
DHB
4263#if defined(TARGET_PPC64)
4264static void pmu_count_insns(DisasContext *ctx)
4265{
4266 /*
4267 * Do not bother calling the helper if the PMU isn't counting
4268 * instructions.
4269 */
4270 if (!ctx->pmu_insn_cnt) {
4271 return;
4272 }
4273
4274 #if !defined(CONFIG_USER_ONLY)
eeaaefe9
LL
4275 TCGLabel *l;
4276 TCGv t0;
4277
46d396bd
DHB
4278 /*
4279 * The PMU insns_inc() helper stops the internal PMU timer if a
4280 * counter overflows happens. In that case, if the guest is
4281 * running with icount and we do not handle it beforehand,
4282 * the helper can trigger a 'bad icount read'.
4283 */
4284 gen_icount_io_start(ctx);
4285
eeaaefe9
LL
4286 /* Avoid helper calls when only PMC5-6 are enabled. */
4287 if (!ctx->pmc_other) {
4288 l = gen_new_label();
4289 t0 = tcg_temp_new();
4290
4291 gen_load_spr(t0, SPR_POWER_PMC5);
4292 tcg_gen_addi_tl(t0, t0, ctx->base.num_insns);
4293 gen_store_spr(SPR_POWER_PMC5, t0);
4294 /* Check for overflow, if it's enabled */
4295 if (ctx->mmcr0_pmcjce) {
4296 tcg_gen_brcondi_tl(TCG_COND_LT, t0, PMC_COUNTER_NEGATIVE_VAL, l);
4297 gen_helper_handle_pmc5_overflow(cpu_env);
4298 }
4299
4300 gen_set_label(l);
4301 tcg_temp_free(t0);
4302 } else {
4303 gen_helper_insns_inc(cpu_env, tcg_constant_i32(ctx->base.num_insns));
4304 }
4305 #else
46d396bd
DHB
4306 /*
4307 * User mode can read (but not write) PMC5 and start/stop
4308 * the PMU via MMCR0_FC. In this case just increment
4309 * PMC5 with base.num_insns.
4310 */
4311 TCGv t0 = tcg_temp_new();
4312
4313 gen_load_spr(t0, SPR_POWER_PMC5);
4314 tcg_gen_addi_tl(t0, t0, ctx->base.num_insns);
4315 gen_store_spr(SPR_POWER_PMC5, t0);
4316
4317 tcg_temp_free(t0);
eeaaefe9 4318 #endif /* #if !defined(CONFIG_USER_ONLY) */
46d396bd
DHB
4319}
4320#else
4321static void pmu_count_insns(DisasContext *ctx)
4322{
4323 return;
4324}
4325#endif /* #if defined(TARGET_PPC64) */
4326
90aa39a1
SF
4327static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4328{
6e9cc373 4329 return translator_use_goto_tb(&ctx->base, dest);
90aa39a1
SF
4330}
4331
0e3bf489
RK
4332static void gen_lookup_and_goto_ptr(DisasContext *ctx)
4333{
9498d103
RH
4334 if (unlikely(ctx->singlestep_enabled)) {
4335 gen_debug_exception(ctx);
0e3bf489 4336 } else {
46d396bd
DHB
4337 /*
4338 * tcg_gen_lookup_and_goto_ptr will exit the TB if
4339 * CF_NO_GOTO_PTR is set. Count insns now.
4340 */
4341 if (ctx->base.tb->flags & CF_NO_GOTO_PTR) {
4342 pmu_count_insns(ctx);
4343 }
4344
0e3bf489
RK
4345 tcg_gen_lookup_and_goto_ptr();
4346 }
4347}
4348
79aceca5 4349/*** Branch ***/
c4a2e3a9 4350static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c1942362 4351{
e0c8f9ce 4352 if (NARROW_MODE(ctx)) {
a2ffb812 4353 dest = (uint32_t) dest;
e0c8f9ce 4354 }
90aa39a1 4355 if (use_goto_tb(ctx, dest)) {
46d396bd 4356 pmu_count_insns(ctx);
57fec1fe 4357 tcg_gen_goto_tb(n);
a2ffb812 4358 tcg_gen_movi_tl(cpu_nip, dest & ~3);
07ea28b4 4359 tcg_gen_exit_tb(ctx->base.tb, n);
c1942362 4360 } else {
a2ffb812 4361 tcg_gen_movi_tl(cpu_nip, dest & ~3);
0e3bf489 4362 gen_lookup_and_goto_ptr(ctx);
c1942362 4363 }
c53be334
FB
4364}
4365
636aa200 4366static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
e1833e1f 4367{
e0c8f9ce
RH
4368 if (NARROW_MODE(ctx)) {
4369 nip = (uint32_t)nip;
4370 }
4371 tcg_gen_movi_tl(cpu_lr, nip);
e1833e1f
JM
4372}
4373
79aceca5 4374/* b ba bl bla */
99e300ef 4375static void gen_b(DisasContext *ctx)
79aceca5 4376{
76a66253 4377 target_ulong li, target;
38a64f9d
FB
4378
4379 /* sign extend LI */
e0c8f9ce
RH
4380 li = LI(ctx->opcode);
4381 li = (li ^ 0x02000000) - 0x02000000;
4382 if (likely(AA(ctx->opcode) == 0)) {
2c2bcb1b 4383 target = ctx->cia + li;
e0c8f9ce 4384 } else {
9a64fbe4 4385 target = li;
e0c8f9ce
RH
4386 }
4387 if (LK(ctx->opcode)) {
b6bac4bc 4388 gen_setlr(ctx, ctx->base.pc_next);
e0c8f9ce 4389 }
2c2bcb1b 4390 gen_update_cfar(ctx, ctx->cia);
c1942362 4391 gen_goto_tb(ctx, 0, target);
6086c751 4392 ctx->base.is_jmp = DISAS_NORETURN;
79aceca5
FB
4393}
4394
e98a6e40
FB
4395#define BCOND_IM 0
4396#define BCOND_LR 1
4397#define BCOND_CTR 2
52a4984d 4398#define BCOND_TAR 3
e98a6e40 4399
c4a2e3a9 4400static void gen_bcond(DisasContext *ctx, int type)
d9bce9d9 4401{
d9bce9d9 4402 uint32_t bo = BO(ctx->opcode);
42a268c2 4403 TCGLabel *l1;
a2ffb812 4404 TCGv target;
0e3bf489 4405
52a4984d 4406 if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
a7812ae4 4407 target = tcg_temp_local_new();
efe843d8 4408 if (type == BCOND_CTR) {
a2ffb812 4409 tcg_gen_mov_tl(target, cpu_ctr);
efe843d8 4410 } else if (type == BCOND_TAR) {
52a4984d 4411 gen_load_spr(target, SPR_TAR);
efe843d8 4412 } else {
a2ffb812 4413 tcg_gen_mov_tl(target, cpu_lr);
efe843d8 4414 }
d2e9fd8f 4415 } else {
f764718d 4416 target = NULL;
e98a6e40 4417 }
efe843d8 4418 if (LK(ctx->opcode)) {
b6bac4bc 4419 gen_setlr(ctx, ctx->base.pc_next);
efe843d8 4420 }
a2ffb812
AJ
4421 l1 = gen_new_label();
4422 if ((bo & 0x4) == 0) {
4423 /* Decrement and test CTR */
a7812ae4 4424 TCGv temp = tcg_temp_new();
fa200c95
GK
4425
4426 if (type == BCOND_CTR) {
4427 /*
4428 * All ISAs up to v3 describe this form of bcctr as invalid but
4429 * some processors, ie. 64-bit server processors compliant with
4430 * arch 2.x, do implement a "test and decrement" logic instead,
15d68c5e
GK
4431 * as described in their respective UMs. This logic involves CTR
4432 * to act as both the branch target and a counter, which makes
4433 * it basically useless and thus never used in real code.
4434 *
4435 * This form was hence chosen to trigger extra micro-architectural
4436 * side-effect on real HW needed for the Spectre v2 workaround.
4437 * It is up to guests that implement such workaround, ie. linux, to
4438 * use this form in a way it just triggers the side-effect without
4439 * doing anything else harmful.
fa200c95 4440 */
d0db7cad 4441 if (unlikely(!is_book3s_arch2x(ctx))) {
fa200c95
GK
4442 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
4443 tcg_temp_free(temp);
4444 tcg_temp_free(target);
4445 return;
4446 }
4447
4448 if (NARROW_MODE(ctx)) {
4449 tcg_gen_ext32u_tl(temp, cpu_ctr);
4450 } else {
4451 tcg_gen_mov_tl(temp, cpu_ctr);
4452 }
4453 if (bo & 0x2) {
4454 tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
4455 } else {
4456 tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
4457 }
4458 tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
a2ffb812 4459 } else {
fa200c95
GK
4460 tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
4461 if (NARROW_MODE(ctx)) {
4462 tcg_gen_ext32u_tl(temp, cpu_ctr);
4463 } else {
4464 tcg_gen_mov_tl(temp, cpu_ctr);
4465 }
4466 if (bo & 0x2) {
4467 tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
4468 } else {
4469 tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
4470 }
e98a6e40 4471 }
a7812ae4 4472 tcg_temp_free(temp);
a2ffb812
AJ
4473 }
4474 if ((bo & 0x10) == 0) {
4475 /* Test CR */
4476 uint32_t bi = BI(ctx->opcode);
8f9fb7ac 4477 uint32_t mask = 0x08 >> (bi & 0x03);
a7812ae4 4478 TCGv_i32 temp = tcg_temp_new_i32();
a2ffb812 4479
d9bce9d9 4480 if (bo & 0x8) {
a2ffb812
AJ
4481 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
4482 tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
d9bce9d9 4483 } else {
a2ffb812
AJ
4484 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
4485 tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
d9bce9d9 4486 }
a7812ae4 4487 tcg_temp_free_i32(temp);
d9bce9d9 4488 }
2c2bcb1b 4489 gen_update_cfar(ctx, ctx->cia);
e98a6e40 4490 if (type == BCOND_IM) {
a2ffb812
AJ
4491 target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
4492 if (likely(AA(ctx->opcode) == 0)) {
2c2bcb1b 4493 gen_goto_tb(ctx, 0, ctx->cia + li);
a2ffb812
AJ
4494 } else {
4495 gen_goto_tb(ctx, 0, li);
4496 }
e98a6e40 4497 } else {
e0c8f9ce 4498 if (NARROW_MODE(ctx)) {
a2ffb812 4499 tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
e0c8f9ce 4500 } else {
a2ffb812 4501 tcg_gen_andi_tl(cpu_nip, target, ~3);
e0c8f9ce 4502 }
0e3bf489 4503 gen_lookup_and_goto_ptr(ctx);
c80d1df5
AG
4504 tcg_temp_free(target);
4505 }
c4a2e3a9 4506 if ((bo & 0x14) != 0x14) {
0e3bf489 4507 /* fallthrough case */
c4a2e3a9 4508 gen_set_label(l1);
b6bac4bc 4509 gen_goto_tb(ctx, 1, ctx->base.pc_next);
c4a2e3a9 4510 }
6086c751 4511 ctx->base.is_jmp = DISAS_NORETURN;
e98a6e40
FB
4512}
4513
99e300ef 4514static void gen_bc(DisasContext *ctx)
3b46e624 4515{
e98a6e40
FB
4516 gen_bcond(ctx, BCOND_IM);
4517}
4518
99e300ef 4519static void gen_bcctr(DisasContext *ctx)
3b46e624 4520{
e98a6e40
FB
4521 gen_bcond(ctx, BCOND_CTR);
4522}
4523
99e300ef 4524static void gen_bclr(DisasContext *ctx)
3b46e624 4525{
e98a6e40
FB
4526 gen_bcond(ctx, BCOND_LR);
4527}
79aceca5 4528
52a4984d
TM
4529static void gen_bctar(DisasContext *ctx)
4530{
4531 gen_bcond(ctx, BCOND_TAR);
4532}
4533
79aceca5 4534/*** Condition register logical ***/
e1571908 4535#define GEN_CRLOGIC(name, tcg_op, opc) \
efe843d8 4536static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 4537{ \
fc0d441e
JM
4538 uint8_t bitmask; \
4539 int sh; \
a7812ae4 4540 TCGv_i32 t0, t1; \
fc0d441e 4541 sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
a7812ae4 4542 t0 = tcg_temp_new_i32(); \
fc0d441e 4543 if (sh > 0) \
fea0c503 4544 tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \
fc0d441e 4545 else if (sh < 0) \
fea0c503 4546 tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \
e1571908 4547 else \
fea0c503 4548 tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \
a7812ae4 4549 t1 = tcg_temp_new_i32(); \
fc0d441e
JM
4550 sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
4551 if (sh > 0) \
fea0c503 4552 tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \
fc0d441e 4553 else if (sh < 0) \
fea0c503 4554 tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \
e1571908 4555 else \
fea0c503
AJ
4556 tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \
4557 tcg_op(t0, t0, t1); \
8f9fb7ac 4558 bitmask = 0x08 >> (crbD(ctx->opcode) & 0x03); \
fea0c503
AJ
4559 tcg_gen_andi_i32(t0, t0, bitmask); \
4560 tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
4561 tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \
a7812ae4
PB
4562 tcg_temp_free_i32(t0); \
4563 tcg_temp_free_i32(t1); \
79aceca5
FB
4564}
4565
4566/* crand */
e1571908 4567GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
79aceca5 4568/* crandc */
e1571908 4569GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
79aceca5 4570/* creqv */
e1571908 4571GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
79aceca5 4572/* crnand */
e1571908 4573GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
79aceca5 4574/* crnor */
e1571908 4575GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
79aceca5 4576/* cror */
e1571908 4577GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
79aceca5 4578/* crorc */
e1571908 4579GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
79aceca5 4580/* crxor */
e1571908 4581GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
99e300ef 4582
54623277 4583/* mcrf */
99e300ef 4584static void gen_mcrf(DisasContext *ctx)
79aceca5 4585{
47e4661c 4586 tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
79aceca5
FB
4587}
4588
4589/*** System linkage ***/
99e300ef 4590
c47493f2 4591/* rfi (supervisor only) */
99e300ef 4592static void gen_rfi(DisasContext *ctx)
79aceca5 4593{
9a64fbe4 4594#if defined(CONFIG_USER_ONLY)
9f0cf041 4595 GEN_PRIV(ctx);
9a64fbe4 4596#else
efe843d8
DG
4597 /*
4598 * This instruction doesn't exist anymore on 64-bit server
6ca038c2 4599 * processors compliant with arch 2.x
a2e71b28 4600 */
d0db7cad 4601 if (is_book3s_arch2x(ctx)) {
6ca038c2
BH
4602 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
4603 return;
4604 }
9a64fbe4 4605 /* Restore CPU state */
9f0cf041 4606 CHK_SV(ctx);
f5b6daac 4607 gen_icount_io_start(ctx);
2c2bcb1b 4608 gen_update_cfar(ctx, ctx->cia);
e5f17ac6 4609 gen_helper_rfi(cpu_env);
59bf23fa 4610 ctx->base.is_jmp = DISAS_EXIT;
9a64fbe4 4611#endif
79aceca5
FB
4612}
4613
426613db 4614#if defined(TARGET_PPC64)
99e300ef 4615static void gen_rfid(DisasContext *ctx)
426613db
JM
4616{
4617#if defined(CONFIG_USER_ONLY)
9f0cf041 4618 GEN_PRIV(ctx);
426613db
JM
4619#else
4620 /* Restore CPU state */
9f0cf041 4621 CHK_SV(ctx);
f5b6daac 4622 gen_icount_io_start(ctx);
2c2bcb1b 4623 gen_update_cfar(ctx, ctx->cia);
e5f17ac6 4624 gen_helper_rfid(cpu_env);
59bf23fa 4625 ctx->base.is_jmp = DISAS_EXIT;
426613db
JM
4626#endif
4627}
426613db 4628
3c89b8d6
NP
4629#if !defined(CONFIG_USER_ONLY)
4630static void gen_rfscv(DisasContext *ctx)
4631{
4632#if defined(CONFIG_USER_ONLY)
9f0cf041 4633 GEN_PRIV(ctx);
3c89b8d6
NP
4634#else
4635 /* Restore CPU state */
9f0cf041 4636 CHK_SV(ctx);
f5b6daac 4637 gen_icount_io_start(ctx);
2c2bcb1b 4638 gen_update_cfar(ctx, ctx->cia);
3c89b8d6 4639 gen_helper_rfscv(cpu_env);
59bf23fa 4640 ctx->base.is_jmp = DISAS_EXIT;
3c89b8d6
NP
4641#endif
4642}
4643#endif
4644
99e300ef 4645static void gen_hrfid(DisasContext *ctx)
be147d08
JM
4646{
4647#if defined(CONFIG_USER_ONLY)
9f0cf041 4648 GEN_PRIV(ctx);
be147d08
JM
4649#else
4650 /* Restore CPU state */
9f0cf041 4651 CHK_HV(ctx);
e5f17ac6 4652 gen_helper_hrfid(cpu_env);
59bf23fa 4653 ctx->base.is_jmp = DISAS_EXIT;
be147d08
JM
4654#endif
4655}
4656#endif
4657
79aceca5 4658/* sc */
417bf010
JM
4659#if defined(CONFIG_USER_ONLY)
4660#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
4661#else
4662#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3c89b8d6 4663#define POWERPC_SYSCALL_VECTORED POWERPC_EXCP_SYSCALL_VECTORED
417bf010 4664#endif
99e300ef 4665static void gen_sc(DisasContext *ctx)
79aceca5 4666{
e1833e1f
JM
4667 uint32_t lev;
4668
4669 lev = (ctx->opcode >> 5) & 0x7F;
e06fcd75 4670 gen_exception_err(ctx, POWERPC_SYSCALL, lev);
79aceca5
FB
4671}
4672
3c89b8d6
NP
4673#if defined(TARGET_PPC64)
4674#if !defined(CONFIG_USER_ONLY)
4675static void gen_scv(DisasContext *ctx)
4676{
f43520e5 4677 uint32_t lev = (ctx->opcode >> 5) & 0x7F;
3c89b8d6 4678
f43520e5 4679 /* Set the PC back to the faulting instruction. */
7a3fe174 4680 gen_update_nip(ctx, ctx->cia);
f43520e5 4681 gen_helper_scv(cpu_env, tcg_constant_i32(lev));
3c89b8d6 4682
7a3fe174 4683 ctx->base.is_jmp = DISAS_NORETURN;
3c89b8d6
NP
4684}
4685#endif
4686#endif
4687
79aceca5 4688/*** Trap ***/
99e300ef 4689
22b56ee5
BH
4690/* Check for unconditional traps (always or never) */
4691static bool check_unconditional_trap(DisasContext *ctx)
4692{
4693 /* Trap never */
4694 if (TO(ctx->opcode) == 0) {
4695 return true;
4696 }
4697 /* Trap always */
4698 if (TO(ctx->opcode) == 31) {
4699 gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
4700 return true;
4701 }
4702 return false;
4703}
4704
54623277 4705/* tw */
99e300ef 4706static void gen_tw(DisasContext *ctx)
79aceca5 4707{
22b56ee5
BH
4708 TCGv_i32 t0;
4709
4710 if (check_unconditional_trap(ctx)) {
4711 return;
4712 }
4713 t0 = tcg_const_i32(TO(ctx->opcode));
e5f17ac6
BS
4714 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4715 t0);
cab3bee2 4716 tcg_temp_free_i32(t0);
79aceca5
FB
4717}
4718
4719/* twi */
99e300ef 4720static void gen_twi(DisasContext *ctx)
79aceca5 4721{
22b56ee5
BH
4722 TCGv t0;
4723 TCGv_i32 t1;
4724
4725 if (check_unconditional_trap(ctx)) {
4726 return;
4727 }
4728 t0 = tcg_const_tl(SIMM(ctx->opcode));
4729 t1 = tcg_const_i32(TO(ctx->opcode));
e5f17ac6 4730 gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
cab3bee2
AJ
4731 tcg_temp_free(t0);
4732 tcg_temp_free_i32(t1);
79aceca5
FB
4733}
4734
d9bce9d9
JM
4735#if defined(TARGET_PPC64)
4736/* td */
99e300ef 4737static void gen_td(DisasContext *ctx)
d9bce9d9 4738{
22b56ee5
BH
4739 TCGv_i32 t0;
4740
4741 if (check_unconditional_trap(ctx)) {
4742 return;
4743 }
4744 t0 = tcg_const_i32(TO(ctx->opcode));
e5f17ac6
BS
4745 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
4746 t0);
cab3bee2 4747 tcg_temp_free_i32(t0);
d9bce9d9
JM
4748}
4749
4750/* tdi */
99e300ef 4751static void gen_tdi(DisasContext *ctx)
d9bce9d9 4752{
22b56ee5
BH
4753 TCGv t0;
4754 TCGv_i32 t1;
4755
4756 if (check_unconditional_trap(ctx)) {
4757 return;
4758 }
4759 t0 = tcg_const_tl(SIMM(ctx->opcode));
4760 t1 = tcg_const_i32(TO(ctx->opcode));
e5f17ac6 4761 gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
cab3bee2
AJ
4762 tcg_temp_free(t0);
4763 tcg_temp_free_i32(t1);
d9bce9d9
JM
4764}
4765#endif
4766
79aceca5 4767/*** Processor control ***/
99e300ef 4768
54623277 4769/* mcrxr */
99e300ef 4770static void gen_mcrxr(DisasContext *ctx)
79aceca5 4771{
da91a00f
RH
4772 TCGv_i32 t0 = tcg_temp_new_i32();
4773 TCGv_i32 t1 = tcg_temp_new_i32();
4774 TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];
4775
4776 tcg_gen_trunc_tl_i32(t0, cpu_so);
4777 tcg_gen_trunc_tl_i32(t1, cpu_ov);
4778 tcg_gen_trunc_tl_i32(dst, cpu_ca);
294d1292
SB
4779 tcg_gen_shli_i32(t0, t0, 3);
4780 tcg_gen_shli_i32(t1, t1, 2);
4781 tcg_gen_shli_i32(dst, dst, 1);
da91a00f
RH
4782 tcg_gen_or_i32(dst, dst, t0);
4783 tcg_gen_or_i32(dst, dst, t1);
4784 tcg_temp_free_i32(t0);
4785 tcg_temp_free_i32(t1);
4786
4787 tcg_gen_movi_tl(cpu_so, 0);
4788 tcg_gen_movi_tl(cpu_ov, 0);
4789 tcg_gen_movi_tl(cpu_ca, 0);
79aceca5
FB
4790}
4791
b63d0434
ND
4792#ifdef TARGET_PPC64
4793/* mcrxrx */
4794static void gen_mcrxrx(DisasContext *ctx)
4795{
4796 TCGv t0 = tcg_temp_new();
4797 TCGv t1 = tcg_temp_new();
4798 TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)];
4799
4800 /* copy OV and OV32 */
4801 tcg_gen_shli_tl(t0, cpu_ov, 1);
4802 tcg_gen_or_tl(t0, t0, cpu_ov32);
4803 tcg_gen_shli_tl(t0, t0, 2);
4804 /* copy CA and CA32 */
4805 tcg_gen_shli_tl(t1, cpu_ca, 1);
4806 tcg_gen_or_tl(t1, t1, cpu_ca32);
4807 tcg_gen_or_tl(t0, t0, t1);
4808 tcg_gen_trunc_tl_i32(dst, t0);
4809 tcg_temp_free(t0);
4810 tcg_temp_free(t1);
4811}
4812#endif
4813
0cfe11ea 4814/* mfcr mfocrf */
99e300ef 4815static void gen_mfcr(DisasContext *ctx)
79aceca5 4816{
76a66253 4817 uint32_t crm, crn;
3b46e624 4818
76a66253
JM
4819 if (likely(ctx->opcode & 0x00100000)) {
4820 crm = CRM(ctx->opcode);
8dd640e4 4821 if (likely(crm && ((crm & (crm - 1)) == 0))) {
efe843d8 4822 crn = ctz32(crm);
e1571908 4823 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
0497d2f4
AJ
4824 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
4825 cpu_gpr[rD(ctx->opcode)], crn * 4);
76a66253 4826 }
d9bce9d9 4827 } else {
651721b2
AJ
4828 TCGv_i32 t0 = tcg_temp_new_i32();
4829 tcg_gen_mov_i32(t0, cpu_crf[0]);
4830 tcg_gen_shli_i32(t0, t0, 4);
4831 tcg_gen_or_i32(t0, t0, cpu_crf[1]);
4832 tcg_gen_shli_i32(t0, t0, 4);
4833 tcg_gen_or_i32(t0, t0, cpu_crf[2]);
4834 tcg_gen_shli_i32(t0, t0, 4);
4835 tcg_gen_or_i32(t0, t0, cpu_crf[3]);
4836 tcg_gen_shli_i32(t0, t0, 4);
4837 tcg_gen_or_i32(t0, t0, cpu_crf[4]);
4838 tcg_gen_shli_i32(t0, t0, 4);
4839 tcg_gen_or_i32(t0, t0, cpu_crf[5]);
4840 tcg_gen_shli_i32(t0, t0, 4);
4841 tcg_gen_or_i32(t0, t0, cpu_crf[6]);
4842 tcg_gen_shli_i32(t0, t0, 4);
4843 tcg_gen_or_i32(t0, t0, cpu_crf[7]);
4844 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
4845 tcg_temp_free_i32(t0);
d9bce9d9 4846 }
79aceca5
FB
4847}
4848
4849/* mfmsr */
99e300ef 4850static void gen_mfmsr(DisasContext *ctx)
79aceca5 4851{
9f0cf041 4852 CHK_SV(ctx);
6527f6ea 4853 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
79aceca5
FB
4854}
4855
4856/* mfspr */
636aa200 4857static inline void gen_op_mfspr(DisasContext *ctx)
79aceca5 4858{
69b058c8 4859 void (*read_cb)(DisasContext *ctx, int gprn, int sprn);
79aceca5
FB
4860 uint32_t sprn = SPR(ctx->opcode);
4861
eb94268e
BH
4862#if defined(CONFIG_USER_ONLY)
4863 read_cb = ctx->spr_cb[sprn].uea_read;
4864#else
4865 if (ctx->pr) {
4866 read_cb = ctx->spr_cb[sprn].uea_read;
4867 } else if (ctx->hv) {
be147d08 4868 read_cb = ctx->spr_cb[sprn].hea_read;
eb94268e 4869 } else {
3fc6c082 4870 read_cb = ctx->spr_cb[sprn].oea_read;
eb94268e 4871 }
9a64fbe4 4872#endif
76a66253
JM
4873 if (likely(read_cb != NULL)) {
4874 if (likely(read_cb != SPR_NOACCESS)) {
45d827d2 4875 (*read_cb)(ctx, rD(ctx->opcode), sprn);
3fc6c082
FB
4876 } else {
4877 /* Privilege exception */
efe843d8
DG
4878 /*
4879 * This is a hack to avoid warnings when running Linux:
9fceefa7
JM
4880 * this OS breaks the PowerPC virtualisation model,
4881 * allowing userland application to read the PVR
4882 */
4883 if (sprn != SPR_PVR) {
31085338
TH
4884 qemu_log_mask(LOG_GUEST_ERROR, "Trying to read privileged spr "
4885 "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
2c2bcb1b 4886 ctx->cia);
f24e5695 4887 }
9b2fadda 4888 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
79aceca5 4889 }
3fc6c082 4890 } else {
9b2fadda
BH
4891 /* ISA 2.07 defines these as no-ops */
4892 if ((ctx->insns_flags2 & PPC2_ISA207S) &&
4893 (sprn >= 808 && sprn <= 811)) {
4894 /* This is a nop */
4895 return;
4896 }
3fc6c082 4897 /* Not defined */
31085338
TH
4898 qemu_log_mask(LOG_GUEST_ERROR,
4899 "Trying to read invalid spr %d (0x%03x) at "
2c2bcb1b 4900 TARGET_FMT_lx "\n", sprn, sprn, ctx->cia);
9b2fadda 4901
efe843d8
DG
4902 /*
4903 * The behaviour depends on MSR:PR and SPR# bit 0x10, it can
4904 * generate a priv, a hv emu or a no-op
9b2fadda
BH
4905 */
4906 if (sprn & 0x10) {
4907 if (ctx->pr) {
1315eed6 4908 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
9b2fadda
BH
4909 }
4910 } else {
4911 if (ctx->pr || sprn == 0 || sprn == 4 || sprn == 5 || sprn == 6) {
1315eed6 4912 gen_hvpriv_exception(ctx, POWERPC_EXCP_PRIV_REG);
9b2fadda 4913 }
4d6a0680 4914 }
79aceca5 4915 }
79aceca5
FB
4916}
4917
99e300ef 4918static void gen_mfspr(DisasContext *ctx)
79aceca5 4919{
3fc6c082 4920 gen_op_mfspr(ctx);
76a66253 4921}
3fc6c082
FB
4922
4923/* mftb */
99e300ef 4924static void gen_mftb(DisasContext *ctx)
3fc6c082
FB
4925{
4926 gen_op_mfspr(ctx);
79aceca5
FB
4927}
4928
0cfe11ea 4929/* mtcrf mtocrf*/
99e300ef 4930static void gen_mtcrf(DisasContext *ctx)
79aceca5 4931{
76a66253 4932 uint32_t crm, crn;
3b46e624 4933
76a66253 4934 crm = CRM(ctx->opcode);
8dd640e4 4935 if (likely((ctx->opcode & 0x00100000))) {
4936 if (crm && ((crm & (crm - 1)) == 0)) {
4937 TCGv_i32 temp = tcg_temp_new_i32();
efe843d8 4938 crn = ctz32(crm);
8dd640e4 4939 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
0cfe11ea
AJ
4940 tcg_gen_shri_i32(temp, temp, crn * 4);
4941 tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
8dd640e4 4942 tcg_temp_free_i32(temp);
4943 }
76a66253 4944 } else {
651721b2
AJ
4945 TCGv_i32 temp = tcg_temp_new_i32();
4946 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
4947 for (crn = 0 ; crn < 8 ; crn++) {
4948 if (crm & (1 << crn)) {
4949 tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
4950 tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
4951 }
4952 }
a7812ae4 4953 tcg_temp_free_i32(temp);
76a66253 4954 }
79aceca5
FB
4955}
4956
4957/* mtmsr */
426613db 4958#if defined(TARGET_PPC64)
99e300ef 4959static void gen_mtmsrd(DisasContext *ctx)
426613db 4960{
caf590dd
NP
4961 if (unlikely(!is_book3s_arch2x(ctx))) {
4962 gen_invalid(ctx);
4963 return;
4964 }
4965
9f0cf041 4966 CHK_SV(ctx);
9b2fadda
BH
4967
4968#if !defined(CONFIG_USER_ONLY)
6fa5726b
MF
4969 TCGv t0, t1;
4970 target_ulong mask;
4971
4972 t0 = tcg_temp_new();
4973 t1 = tcg_temp_new();
4974
f5b6daac 4975 gen_icount_io_start(ctx);
6fa5726b 4976
be147d08 4977 if (ctx->opcode & 0x00010000) {
5ed19506 4978 /* L=1 form only updates EE and RI */
6fa5726b 4979 mask = (1ULL << MSR_RI) | (1ULL << MSR_EE);
be147d08 4980 } else {
6fa5726b
MF
4981 /* mtmsrd does not alter HV, S, ME, or LE */
4982 mask = ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S) |
4983 (1ULL << MSR_HV));
efe843d8
DG
4984 /*
4985 * XXX: we need to update nip before the store if we enter
4986 * power saving mode, we will exit the loop directly from
4987 * ppc_store_msr
056b05f8 4988 */
b6bac4bc 4989 gen_update_nip(ctx, ctx->base.pc_next);
be147d08 4990 }
6fa5726b
MF
4991
4992 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], mask);
4993 tcg_gen_andi_tl(t1, cpu_msr, ~mask);
4994 tcg_gen_or_tl(t0, t0, t1);
4995
4996 gen_helper_store_msr(cpu_env, t0);
4997
5ed19506 4998 /* Must stop the translation as machine state (may have) changed */
d736de8f 4999 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
6fa5726b
MF
5000
5001 tcg_temp_free(t0);
5002 tcg_temp_free(t1);
9b2fadda 5003#endif /* !defined(CONFIG_USER_ONLY) */
426613db 5004}
9b2fadda 5005#endif /* defined(TARGET_PPC64) */
426613db 5006
99e300ef 5007static void gen_mtmsr(DisasContext *ctx)
79aceca5 5008{
9f0cf041 5009 CHK_SV(ctx);
9b2fadda
BH
5010
5011#if !defined(CONFIG_USER_ONLY)
6fa5726b
MF
5012 TCGv t0, t1;
5013 target_ulong mask = 0xFFFFFFFF;
5014
5015 t0 = tcg_temp_new();
5016 t1 = tcg_temp_new();
5017
f5b6daac 5018 gen_icount_io_start(ctx);
5ed19506
NP
5019 if (ctx->opcode & 0x00010000) {
5020 /* L=1 form only updates EE and RI */
6fa5726b 5021 mask &= (1ULL << MSR_RI) | (1ULL << MSR_EE);
be147d08 5022 } else {
6fa5726b
MF
5023 /* mtmsr does not alter S, ME, or LE */
5024 mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
8018dc63 5025
efe843d8
DG
5026 /*
5027 * XXX: we need to update nip before the store if we enter
5028 * power saving mode, we will exit the loop directly from
5029 * ppc_store_msr
056b05f8 5030 */
b6bac4bc 5031 gen_update_nip(ctx, ctx->base.pc_next);
be147d08 5032 }
6fa5726b
MF
5033
5034 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], mask);
5035 tcg_gen_andi_tl(t1, cpu_msr, ~mask);
5036 tcg_gen_or_tl(t0, t0, t1);
5037
5038 gen_helper_store_msr(cpu_env, t0);
5039
5ed19506 5040 /* Must stop the translation as machine state (may have) changed */
d736de8f 5041 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
6fa5726b
MF
5042
5043 tcg_temp_free(t0);
5044 tcg_temp_free(t1);
9a64fbe4 5045#endif
79aceca5
FB
5046}
5047
5048/* mtspr */
99e300ef 5049static void gen_mtspr(DisasContext *ctx)
79aceca5 5050{
69b058c8 5051 void (*write_cb)(DisasContext *ctx, int sprn, int gprn);
79aceca5
FB
5052 uint32_t sprn = SPR(ctx->opcode);
5053
eb94268e
BH
5054#if defined(CONFIG_USER_ONLY)
5055 write_cb = ctx->spr_cb[sprn].uea_write;
5056#else
5057 if (ctx->pr) {
5058 write_cb = ctx->spr_cb[sprn].uea_write;
5059 } else if (ctx->hv) {
be147d08 5060 write_cb = ctx->spr_cb[sprn].hea_write;
eb94268e 5061 } else {
3fc6c082 5062 write_cb = ctx->spr_cb[sprn].oea_write;
eb94268e 5063 }
9a64fbe4 5064#endif
76a66253
JM
5065 if (likely(write_cb != NULL)) {
5066 if (likely(write_cb != SPR_NOACCESS)) {
45d827d2 5067 (*write_cb)(ctx, sprn, rS(ctx->opcode));
3fc6c082
FB
5068 } else {
5069 /* Privilege exception */
31085338
TH
5070 qemu_log_mask(LOG_GUEST_ERROR, "Trying to write privileged spr "
5071 "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
2c2bcb1b 5072 ctx->cia);
9b2fadda 5073 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253 5074 }
3fc6c082 5075 } else {
9b2fadda
BH
5076 /* ISA 2.07 defines these as no-ops */
5077 if ((ctx->insns_flags2 & PPC2_ISA207S) &&
5078 (sprn >= 808 && sprn <= 811)) {
5079 /* This is a nop */
5080 return;
5081 }
5082
3fc6c082 5083 /* Not defined */
31085338
TH
5084 qemu_log_mask(LOG_GUEST_ERROR,
5085 "Trying to write invalid spr %d (0x%03x) at "
2c2bcb1b 5086 TARGET_FMT_lx "\n", sprn, sprn, ctx->cia);
4d6a0680 5087
9b2fadda 5088
efe843d8
DG
5089 /*
5090 * The behaviour depends on MSR:PR and SPR# bit 0x10, it can
5091 * generate a priv, a hv emu or a no-op
9b2fadda
BH
5092 */
5093 if (sprn & 0x10) {
5094 if (ctx->pr) {
1315eed6 5095 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
9b2fadda
BH
5096 }
5097 } else {
5098 if (ctx->pr || sprn == 0) {
1315eed6 5099 gen_hvpriv_exception(ctx, POWERPC_EXCP_PRIV_REG);
9b2fadda 5100 }
4d6a0680 5101 }
79aceca5 5102 }
79aceca5
FB
5103}
5104
dc2ee038
VAS
5105#if defined(TARGET_PPC64)
5106/* setb */
5107static void gen_setb(DisasContext *ctx)
5108{
5109 TCGv_i32 t0 = tcg_temp_new_i32();
6f4912a4
PMD
5110 TCGv_i32 t8 = tcg_constant_i32(8);
5111 TCGv_i32 tm1 = tcg_constant_i32(-1);
dc2ee038
VAS
5112 int crf = crfS(ctx->opcode);
5113
5114 tcg_gen_setcondi_i32(TCG_COND_GEU, t0, cpu_crf[crf], 4);
dc2ee038
VAS
5115 tcg_gen_movcond_i32(TCG_COND_GEU, t0, cpu_crf[crf], t8, tm1, t0);
5116 tcg_gen_ext_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
5117
5118 tcg_temp_free_i32(t0);
dc2ee038
VAS
5119}
5120#endif
5121
79aceca5 5122/*** Cache management ***/
99e300ef 5123
54623277 5124/* dcbf */
99e300ef 5125static void gen_dcbf(DisasContext *ctx)
79aceca5 5126{
dac454af 5127 /* XXX: specification says this is treated as a load by the MMU */
76db3ba4
AJ
5128 TCGv t0;
5129 gen_set_access_type(ctx, ACCESS_CACHE);
5130 t0 = tcg_temp_new();
5131 gen_addr_reg_index(ctx, t0);
5132 gen_qemu_ld8u(ctx, t0, t0);
fea0c503 5133 tcg_temp_free(t0);
79aceca5
FB
5134}
5135
50728199
RK
5136/* dcbfep (external PID dcbf) */
5137static void gen_dcbfep(DisasContext *ctx)
5138{
5139 /* XXX: specification says this is treated as a load by the MMU */
5140 TCGv t0;
9f0cf041 5141 CHK_SV(ctx);
50728199
RK
5142 gen_set_access_type(ctx, ACCESS_CACHE);
5143 t0 = tcg_temp_new();
5144 gen_addr_reg_index(ctx, t0);
5145 tcg_gen_qemu_ld_tl(t0, t0, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UB));
5146 tcg_temp_free(t0);
5147}
5148
79aceca5 5149/* dcbi (Supervisor only) */
99e300ef 5150static void gen_dcbi(DisasContext *ctx)
79aceca5 5151{
a541f297 5152#if defined(CONFIG_USER_ONLY)
9f0cf041 5153 GEN_PRIV(ctx);
a541f297 5154#else
b61f2753 5155 TCGv EA, val;
9b2fadda 5156
9f0cf041 5157 CHK_SV(ctx);
a7812ae4 5158 EA = tcg_temp_new();
76db3ba4
AJ
5159 gen_set_access_type(ctx, ACCESS_CACHE);
5160 gen_addr_reg_index(ctx, EA);
a7812ae4 5161 val = tcg_temp_new();
76a66253 5162 /* XXX: specification says this should be treated as a store by the MMU */
76db3ba4
AJ
5163 gen_qemu_ld8u(ctx, val, EA);
5164 gen_qemu_st8(ctx, val, EA);
b61f2753
AJ
5165 tcg_temp_free(val);
5166 tcg_temp_free(EA);
9b2fadda 5167#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
5168}
5169
5170/* dcdst */
99e300ef 5171static void gen_dcbst(DisasContext *ctx)
79aceca5 5172{
76a66253 5173 /* XXX: specification say this is treated as a load by the MMU */
76db3ba4
AJ
5174 TCGv t0;
5175 gen_set_access_type(ctx, ACCESS_CACHE);
5176 t0 = tcg_temp_new();
5177 gen_addr_reg_index(ctx, t0);
5178 gen_qemu_ld8u(ctx, t0, t0);
fea0c503 5179 tcg_temp_free(t0);
79aceca5
FB
5180}
5181
50728199
RK
5182/* dcbstep (dcbstep External PID version) */
5183static void gen_dcbstep(DisasContext *ctx)
5184{
5185 /* XXX: specification say this is treated as a load by the MMU */
5186 TCGv t0;
5187 gen_set_access_type(ctx, ACCESS_CACHE);
5188 t0 = tcg_temp_new();
5189 gen_addr_reg_index(ctx, t0);
5190 tcg_gen_qemu_ld_tl(t0, t0, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UB));
5191 tcg_temp_free(t0);
5192}
5193
79aceca5 5194/* dcbt */
99e300ef 5195static void gen_dcbt(DisasContext *ctx)
79aceca5 5196{
efe843d8
DG
5197 /*
5198 * interpreted as no-op
5199 * XXX: specification say this is treated as a load by the MMU but
5200 * does not generate any exception
76a66253 5201 */
79aceca5
FB
5202}
5203
50728199
RK
5204/* dcbtep */
5205static void gen_dcbtep(DisasContext *ctx)
5206{
efe843d8
DG
5207 /*
5208 * interpreted as no-op
5209 * XXX: specification say this is treated as a load by the MMU but
5210 * does not generate any exception
50728199
RK
5211 */
5212}
5213
79aceca5 5214/* dcbtst */
99e300ef 5215static void gen_dcbtst(DisasContext *ctx)
79aceca5 5216{
efe843d8
DG
5217 /*
5218 * interpreted as no-op
5219 * XXX: specification say this is treated as a load by the MMU but
5220 * does not generate any exception
76a66253 5221 */
79aceca5
FB
5222}
5223
50728199
RK
5224/* dcbtstep */
5225static void gen_dcbtstep(DisasContext *ctx)
5226{
efe843d8
DG
5227 /*
5228 * interpreted as no-op
5229 * XXX: specification say this is treated as a load by the MMU but
5230 * does not generate any exception
50728199
RK
5231 */
5232}
5233
4d09d529
AG
5234/* dcbtls */
5235static void gen_dcbtls(DisasContext *ctx)
5236{
5237 /* Always fails locking the cache */
5238 TCGv t0 = tcg_temp_new();
5239 gen_load_spr(t0, SPR_Exxx_L1CSR0);
5240 tcg_gen_ori_tl(t0, t0, L1CSR0_CUL);
5241 gen_store_spr(SPR_Exxx_L1CSR0, t0);
5242 tcg_temp_free(t0);
5243}
5244
79aceca5 5245/* dcbz */
99e300ef 5246static void gen_dcbz(DisasContext *ctx)
79aceca5 5247{
8e33944f 5248 TCGv tcgv_addr;
c9f82d01 5249 TCGv_i32 tcgv_op;
d63001d1 5250
76db3ba4 5251 gen_set_access_type(ctx, ACCESS_CACHE);
8e33944f 5252 tcgv_addr = tcg_temp_new();
c9f82d01 5253 tcgv_op = tcg_const_i32(ctx->opcode & 0x03FF000);
8e33944f 5254 gen_addr_reg_index(ctx, tcgv_addr);
c9f82d01 5255 gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_op);
8e33944f 5256 tcg_temp_free(tcgv_addr);
c9f82d01 5257 tcg_temp_free_i32(tcgv_op);
79aceca5
FB
5258}
5259
50728199
RK
5260/* dcbzep */
5261static void gen_dcbzep(DisasContext *ctx)
5262{
5263 TCGv tcgv_addr;
5264 TCGv_i32 tcgv_op;
5265
5266 gen_set_access_type(ctx, ACCESS_CACHE);
5267 tcgv_addr = tcg_temp_new();
5268 tcgv_op = tcg_const_i32(ctx->opcode & 0x03FF000);
5269 gen_addr_reg_index(ctx, tcgv_addr);
5270 gen_helper_dcbzep(cpu_env, tcgv_addr, tcgv_op);
5271 tcg_temp_free(tcgv_addr);
5272 tcg_temp_free_i32(tcgv_op);
5273}
5274
ae1c1a3d 5275/* dst / dstt */
99e300ef 5276static void gen_dst(DisasContext *ctx)
ae1c1a3d
AJ
5277{
5278 if (rA(ctx->opcode) == 0) {
e41029b3 5279 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
ae1c1a3d
AJ
5280 } else {
5281 /* interpreted as no-op */
5282 }
5283}
5284
5285/* dstst /dststt */
99e300ef 5286static void gen_dstst(DisasContext *ctx)
ae1c1a3d
AJ
5287{
5288 if (rA(ctx->opcode) == 0) {
e41029b3 5289 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
ae1c1a3d
AJ
5290 } else {
5291 /* interpreted as no-op */
5292 }
5293
5294}
5295
5296/* dss / dssall */
99e300ef 5297static void gen_dss(DisasContext *ctx)
ae1c1a3d
AJ
5298{
5299 /* interpreted as no-op */
5300}
5301
79aceca5 5302/* icbi */
99e300ef 5303static void gen_icbi(DisasContext *ctx)
79aceca5 5304{
76db3ba4
AJ
5305 TCGv t0;
5306 gen_set_access_type(ctx, ACCESS_CACHE);
76db3ba4
AJ
5307 t0 = tcg_temp_new();
5308 gen_addr_reg_index(ctx, t0);
2f5a189c 5309 gen_helper_icbi(cpu_env, t0);
37d269df 5310 tcg_temp_free(t0);
79aceca5
FB
5311}
5312
50728199
RK
5313/* icbiep */
5314static void gen_icbiep(DisasContext *ctx)
5315{
5316 TCGv t0;
5317 gen_set_access_type(ctx, ACCESS_CACHE);
5318 t0 = tcg_temp_new();
5319 gen_addr_reg_index(ctx, t0);
5320 gen_helper_icbiep(cpu_env, t0);
5321 tcg_temp_free(t0);
5322}
5323
79aceca5
FB
5324/* Optional: */
5325/* dcba */
99e300ef 5326static void gen_dcba(DisasContext *ctx)
79aceca5 5327{
efe843d8
DG
5328 /*
5329 * interpreted as no-op
5330 * XXX: specification say this is treated as a store by the MMU
0db1b20e
JM
5331 * but does not generate any exception
5332 */
79aceca5
FB
5333}
5334
5335/*** Segment register manipulation ***/
5336/* Supervisor only: */
99e300ef 5337
54623277 5338/* mfsr */
99e300ef 5339static void gen_mfsr(DisasContext *ctx)
79aceca5 5340{
9a64fbe4 5341#if defined(CONFIG_USER_ONLY)
9f0cf041 5342 GEN_PRIV(ctx);
9a64fbe4 5343#else
74d37793 5344 TCGv t0;
9b2fadda 5345
9f0cf041 5346 CHK_SV(ctx);
74d37793 5347 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 5348 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 5349 tcg_temp_free(t0);
9b2fadda 5350#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
5351}
5352
5353/* mfsrin */
99e300ef 5354static void gen_mfsrin(DisasContext *ctx)
79aceca5 5355{
9a64fbe4 5356#if defined(CONFIG_USER_ONLY)
9f0cf041 5357 GEN_PRIV(ctx);
9a64fbe4 5358#else
74d37793 5359 TCGv t0;
9b2fadda 5360
9f0cf041 5361 CHK_SV(ctx);
74d37793 5362 t0 = tcg_temp_new();
e2622073 5363 tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
c6c7cf05 5364 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 5365 tcg_temp_free(t0);
9b2fadda 5366#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
5367}
5368
5369/* mtsr */
99e300ef 5370static void gen_mtsr(DisasContext *ctx)
79aceca5 5371{
9a64fbe4 5372#if defined(CONFIG_USER_ONLY)
9f0cf041 5373 GEN_PRIV(ctx);
9a64fbe4 5374#else
74d37793 5375 TCGv t0;
9b2fadda 5376
9f0cf041 5377 CHK_SV(ctx);
74d37793 5378 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 5379 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 5380 tcg_temp_free(t0);
9b2fadda 5381#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
5382}
5383
5384/* mtsrin */
99e300ef 5385static void gen_mtsrin(DisasContext *ctx)
79aceca5 5386{
9a64fbe4 5387#if defined(CONFIG_USER_ONLY)
9f0cf041 5388 GEN_PRIV(ctx);
9a64fbe4 5389#else
74d37793 5390 TCGv t0;
9f0cf041 5391 CHK_SV(ctx);
9b2fadda 5392
74d37793 5393 t0 = tcg_temp_new();
e2622073 5394 tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
c6c7cf05 5395 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]);
74d37793 5396 tcg_temp_free(t0);
9b2fadda 5397#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
5398}
5399
12de9a39
JM
5400#if defined(TARGET_PPC64)
5401/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
e8eaa2c0 5402
54623277 5403/* mfsr */
e8eaa2c0 5404static void gen_mfsr_64b(DisasContext *ctx)
12de9a39
JM
5405{
5406#if defined(CONFIG_USER_ONLY)
9f0cf041 5407 GEN_PRIV(ctx);
12de9a39 5408#else
74d37793 5409 TCGv t0;
9b2fadda 5410
9f0cf041 5411 CHK_SV(ctx);
74d37793 5412 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 5413 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 5414 tcg_temp_free(t0);
9b2fadda 5415#endif /* defined(CONFIG_USER_ONLY) */
12de9a39
JM
5416}
5417
5418/* mfsrin */
e8eaa2c0 5419static void gen_mfsrin_64b(DisasContext *ctx)
12de9a39
JM
5420{
5421#if defined(CONFIG_USER_ONLY)
9f0cf041 5422 GEN_PRIV(ctx);
12de9a39 5423#else
74d37793 5424 TCGv t0;
9b2fadda 5425
9f0cf041 5426 CHK_SV(ctx);
74d37793 5427 t0 = tcg_temp_new();
e2622073 5428 tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
c6c7cf05 5429 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793 5430 tcg_temp_free(t0);
9b2fadda 5431#endif /* defined(CONFIG_USER_ONLY) */
12de9a39
JM
5432}
5433
5434/* mtsr */
e8eaa2c0 5435static void gen_mtsr_64b(DisasContext *ctx)
12de9a39
JM
5436{
5437#if defined(CONFIG_USER_ONLY)
9f0cf041 5438 GEN_PRIV(ctx);
12de9a39 5439#else
74d37793 5440 TCGv t0;
9b2fadda 5441
9f0cf041 5442 CHK_SV(ctx);
74d37793 5443 t0 = tcg_const_tl(SR(ctx->opcode));
c6c7cf05 5444 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 5445 tcg_temp_free(t0);
9b2fadda 5446#endif /* defined(CONFIG_USER_ONLY) */
12de9a39
JM
5447}
5448
5449/* mtsrin */
e8eaa2c0 5450static void gen_mtsrin_64b(DisasContext *ctx)
12de9a39
JM
5451{
5452#if defined(CONFIG_USER_ONLY)
9f0cf041 5453 GEN_PRIV(ctx);
12de9a39 5454#else
74d37793 5455 TCGv t0;
9b2fadda 5456
9f0cf041 5457 CHK_SV(ctx);
74d37793 5458 t0 = tcg_temp_new();
e2622073 5459 tcg_gen_extract_tl(t0, cpu_gpr[rB(ctx->opcode)], 28, 4);
c6c7cf05 5460 gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 5461 tcg_temp_free(t0);
9b2fadda 5462#endif /* defined(CONFIG_USER_ONLY) */
12de9a39 5463}
f6b868fc 5464
12de9a39
JM
5465#endif /* defined(TARGET_PPC64) */
5466
79aceca5 5467/*** Lookaside buffer management ***/
c47493f2 5468/* Optional & supervisor only: */
99e300ef 5469
54623277 5470/* tlbia */
99e300ef 5471static void gen_tlbia(DisasContext *ctx)
79aceca5 5472{
9a64fbe4 5473#if defined(CONFIG_USER_ONLY)
9f0cf041 5474 GEN_PRIV(ctx);
9a64fbe4 5475#else
9f0cf041 5476 CHK_HV(ctx);
9b2fadda 5477
c6c7cf05 5478 gen_helper_tlbia(cpu_env);
9b2fadda 5479#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
5480}
5481
79aceca5 5482/* tlbsync */
99e300ef 5483static void gen_tlbsync(DisasContext *ctx)
79aceca5 5484{
9a64fbe4 5485#if defined(CONFIG_USER_ONLY)
9f0cf041 5486 GEN_PRIV(ctx);
9a64fbe4 5487#else
91c60f12
CLG
5488
5489 if (ctx->gtse) {
9f0cf041 5490 CHK_SV(ctx); /* If gtse is set then tlbsync is supervisor privileged */
91c60f12 5491 } else {
9f0cf041 5492 CHK_HV(ctx); /* Else hypervisor privileged */
91c60f12 5493 }
9b2fadda 5494
e3cffe6f
ND
5495 /* BookS does both ptesync and tlbsync make tlbsync a nop for server */
5496 if (ctx->insns_flags & PPC_BOOKE) {
5497 gen_check_tlb_flush(ctx, true);
5498 }
9b2fadda 5499#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
5500}
5501
5502/*** External control ***/
5503/* Optional: */
99e300ef 5504
54623277 5505/* eciwx */
99e300ef 5506static void gen_eciwx(DisasContext *ctx)
79aceca5 5507{
76db3ba4 5508 TCGv t0;
fa407c03 5509 /* Should check EAR[E] ! */
76db3ba4
AJ
5510 gen_set_access_type(ctx, ACCESS_EXT);
5511 t0 = tcg_temp_new();
5512 gen_addr_reg_index(ctx, t0);
c674a983
RH
5513 tcg_gen_qemu_ld_tl(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx,
5514 DEF_MEMOP(MO_UL | MO_ALIGN));
fa407c03 5515 tcg_temp_free(t0);
76a66253
JM
5516}
5517
5518/* ecowx */
99e300ef 5519static void gen_ecowx(DisasContext *ctx)
76a66253 5520{
76db3ba4 5521 TCGv t0;
fa407c03 5522 /* Should check EAR[E] ! */
76db3ba4
AJ
5523 gen_set_access_type(ctx, ACCESS_EXT);
5524 t0 = tcg_temp_new();
5525 gen_addr_reg_index(ctx, t0);
c674a983
RH
5526 tcg_gen_qemu_st_tl(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx,
5527 DEF_MEMOP(MO_UL | MO_ALIGN));
fa407c03 5528 tcg_temp_free(t0);
76a66253
JM
5529}
5530
76a66253 5531/* 602 - 603 - G2 TLB management */
e8eaa2c0 5532
54623277 5533/* tlbld */
e8eaa2c0 5534static void gen_tlbld_6xx(DisasContext *ctx)
76a66253
JM
5535{
5536#if defined(CONFIG_USER_ONLY)
9f0cf041 5537 GEN_PRIV(ctx);
76a66253 5538#else
9f0cf041 5539 CHK_SV(ctx);
c6c7cf05 5540 gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9b2fadda 5541#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5542}
5543
5544/* tlbli */
e8eaa2c0 5545static void gen_tlbli_6xx(DisasContext *ctx)
76a66253
JM
5546{
5547#if defined(CONFIG_USER_ONLY)
9f0cf041 5548 GEN_PRIV(ctx);
76a66253 5549#else
9f0cf041 5550 CHK_SV(ctx);
c6c7cf05 5551 gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]);
9b2fadda 5552#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5553}
5554
76a66253 5555/* BookE specific instructions */
99e300ef 5556
54623277 5557/* XXX: not implemented on 440 ? */
99e300ef 5558static void gen_mfapidi(DisasContext *ctx)
76a66253
JM
5559{
5560 /* XXX: TODO */
e06fcd75 5561 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5562}
5563
2662a059 5564/* XXX: not implemented on 440 ? */
99e300ef 5565static void gen_tlbiva(DisasContext *ctx)
76a66253
JM
5566{
5567#if defined(CONFIG_USER_ONLY)
9f0cf041 5568 GEN_PRIV(ctx);
76a66253 5569#else
74d37793 5570 TCGv t0;
9b2fadda 5571
9f0cf041 5572 CHK_SV(ctx);
ec72e276 5573 t0 = tcg_temp_new();
76db3ba4 5574 gen_addr_reg_index(ctx, t0);
4693364f 5575 gen_helper_tlbiva(cpu_env, cpu_gpr[rB(ctx->opcode)]);
74d37793 5576 tcg_temp_free(t0);
9b2fadda 5577#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5578}
5579
5580/* All 405 MAC instructions are translated here */
636aa200
BS
5581static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
5582 int ra, int rb, int rt, int Rc)
76a66253 5583{
182608d4
AJ
5584 TCGv t0, t1;
5585
a7812ae4
PB
5586 t0 = tcg_temp_local_new();
5587 t1 = tcg_temp_local_new();
182608d4 5588
76a66253
JM
5589 switch (opc3 & 0x0D) {
5590 case 0x05:
5591 /* macchw - macchw. - macchwo - macchwo. */
5592 /* macchws - macchws. - macchwso - macchwso. */
5593 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5594 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5595 /* mulchw - mulchw. */
182608d4
AJ
5596 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5597 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5598 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5599 break;
5600 case 0x04:
5601 /* macchwu - macchwu. - macchwuo - macchwuo. */
5602 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5603 /* mulchwu - mulchwu. */
182608d4
AJ
5604 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5605 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5606 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5607 break;
5608 case 0x01:
5609 /* machhw - machhw. - machhwo - machhwo. */
5610 /* machhws - machhws. - machhwso - machhwso. */
5611 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5612 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5613 /* mulhhw - mulhhw. */
182608d4
AJ
5614 tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5615 tcg_gen_ext16s_tl(t0, t0);
5616 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5617 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5618 break;
5619 case 0x00:
5620 /* machhwu - machhwu. - machhwuo - machhwuo. */
5621 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5622 /* mulhhwu - mulhhwu. */
182608d4
AJ
5623 tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5624 tcg_gen_ext16u_tl(t0, t0);
5625 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5626 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5627 break;
5628 case 0x0D:
5629 /* maclhw - maclhw. - maclhwo - maclhwo. */
5630 /* maclhws - maclhws. - maclhwso - maclhwso. */
5631 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5632 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5633 /* mullhw - mullhw. */
182608d4
AJ
5634 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5635 tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
76a66253
JM
5636 break;
5637 case 0x0C:
5638 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5639 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5640 /* mullhwu - mullhwu. */
182608d4
AJ
5641 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5642 tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
76a66253
JM
5643 break;
5644 }
76a66253 5645 if (opc2 & 0x04) {
182608d4
AJ
5646 /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5647 tcg_gen_mul_tl(t1, t0, t1);
5648 if (opc2 & 0x02) {
5649 /* nmultiply-and-accumulate (0x0E) */
5650 tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5651 } else {
5652 /* multiply-and-accumulate (0x0C) */
5653 tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5654 }
5655
5656 if (opc3 & 0x12) {
5657 /* Check overflow and/or saturate */
42a268c2 5658 TCGLabel *l1 = gen_new_label();
182608d4
AJ
5659
5660 if (opc3 & 0x10) {
5661 /* Start with XER OV disabled, the most likely case */
da91a00f 5662 tcg_gen_movi_tl(cpu_ov, 0);
182608d4
AJ
5663 }
5664 if (opc3 & 0x01) {
5665 /* Signed */
5666 tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5667 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5668 tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5669 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
bdc4e053 5670 if (opc3 & 0x02) {
182608d4
AJ
5671 /* Saturate */
5672 tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5673 tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5674 }
5675 } else {
5676 /* Unsigned */
5677 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
bdc4e053 5678 if (opc3 & 0x02) {
182608d4
AJ
5679 /* Saturate */
5680 tcg_gen_movi_tl(t0, UINT32_MAX);
5681 }
5682 }
5683 if (opc3 & 0x10) {
5684 /* Check overflow */
da91a00f
RH
5685 tcg_gen_movi_tl(cpu_ov, 1);
5686 tcg_gen_movi_tl(cpu_so, 1);
182608d4
AJ
5687 }
5688 gen_set_label(l1);
5689 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5690 }
5691 } else {
5692 tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
76a66253 5693 }
182608d4
AJ
5694 tcg_temp_free(t0);
5695 tcg_temp_free(t1);
76a66253
JM
5696 if (unlikely(Rc) != 0) {
5697 /* Update Rc0 */
182608d4 5698 gen_set_Rc0(ctx, cpu_gpr[rt]);
76a66253
JM
5699 }
5700}
5701
a750fc0b 5702#define GEN_MAC_HANDLER(name, opc2, opc3) \
99e300ef 5703static void glue(gen_, name)(DisasContext *ctx) \
76a66253
JM
5704{ \
5705 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5706 rD(ctx->opcode), Rc(ctx->opcode)); \
5707}
5708
5709/* macchw - macchw. */
a750fc0b 5710GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
76a66253 5711/* macchwo - macchwo. */
a750fc0b 5712GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
76a66253 5713/* macchws - macchws. */
a750fc0b 5714GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
76a66253 5715/* macchwso - macchwso. */
a750fc0b 5716GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
76a66253 5717/* macchwsu - macchwsu. */
a750fc0b 5718GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
76a66253 5719/* macchwsuo - macchwsuo. */
a750fc0b 5720GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
76a66253 5721/* macchwu - macchwu. */
a750fc0b 5722GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
76a66253 5723/* macchwuo - macchwuo. */
a750fc0b 5724GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
76a66253 5725/* machhw - machhw. */
a750fc0b 5726GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
76a66253 5727/* machhwo - machhwo. */
a750fc0b 5728GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
76a66253 5729/* machhws - machhws. */
a750fc0b 5730GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
76a66253 5731/* machhwso - machhwso. */
a750fc0b 5732GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
76a66253 5733/* machhwsu - machhwsu. */
a750fc0b 5734GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
76a66253 5735/* machhwsuo - machhwsuo. */
a750fc0b 5736GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
76a66253 5737/* machhwu - machhwu. */
a750fc0b 5738GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
76a66253 5739/* machhwuo - machhwuo. */
a750fc0b 5740GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
76a66253 5741/* maclhw - maclhw. */
a750fc0b 5742GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
76a66253 5743/* maclhwo - maclhwo. */
a750fc0b 5744GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
76a66253 5745/* maclhws - maclhws. */
a750fc0b 5746GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
76a66253 5747/* maclhwso - maclhwso. */
a750fc0b 5748GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
76a66253 5749/* maclhwu - maclhwu. */
a750fc0b 5750GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
76a66253 5751/* maclhwuo - maclhwuo. */
a750fc0b 5752GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
76a66253 5753/* maclhwsu - maclhwsu. */
a750fc0b 5754GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
76a66253 5755/* maclhwsuo - maclhwsuo. */
a750fc0b 5756GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
76a66253 5757/* nmacchw - nmacchw. */
a750fc0b 5758GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
76a66253 5759/* nmacchwo - nmacchwo. */
a750fc0b 5760GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
76a66253 5761/* nmacchws - nmacchws. */
a750fc0b 5762GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
76a66253 5763/* nmacchwso - nmacchwso. */
a750fc0b 5764GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
76a66253 5765/* nmachhw - nmachhw. */
a750fc0b 5766GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
76a66253 5767/* nmachhwo - nmachhwo. */
a750fc0b 5768GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
76a66253 5769/* nmachhws - nmachhws. */
a750fc0b 5770GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
76a66253 5771/* nmachhwso - nmachhwso. */
a750fc0b 5772GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
76a66253 5773/* nmaclhw - nmaclhw. */
a750fc0b 5774GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
76a66253 5775/* nmaclhwo - nmaclhwo. */
a750fc0b 5776GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
76a66253 5777/* nmaclhws - nmaclhws. */
a750fc0b 5778GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
76a66253 5779/* nmaclhwso - nmaclhwso. */
a750fc0b 5780GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
76a66253
JM
5781
5782/* mulchw - mulchw. */
a750fc0b 5783GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
76a66253 5784/* mulchwu - mulchwu. */
a750fc0b 5785GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
76a66253 5786/* mulhhw - mulhhw. */
a750fc0b 5787GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
76a66253 5788/* mulhhwu - mulhhwu. */
a750fc0b 5789GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
76a66253 5790/* mullhw - mullhw. */
a750fc0b 5791GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
76a66253 5792/* mullhwu - mullhwu. */
a750fc0b 5793GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
76a66253
JM
5794
5795/* mfdcr */
99e300ef 5796static void gen_mfdcr(DisasContext *ctx)
76a66253
JM
5797{
5798#if defined(CONFIG_USER_ONLY)
9f0cf041 5799 GEN_PRIV(ctx);
76a66253 5800#else
06dca6a7 5801 TCGv dcrn;
9b2fadda 5802
9f0cf041 5803 CHK_SV(ctx);
06dca6a7 5804 dcrn = tcg_const_tl(SPR(ctx->opcode));
d0f1562d 5805 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn);
06dca6a7 5806 tcg_temp_free(dcrn);
9b2fadda 5807#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5808}
5809
5810/* mtdcr */
99e300ef 5811static void gen_mtdcr(DisasContext *ctx)
76a66253
JM
5812{
5813#if defined(CONFIG_USER_ONLY)
9f0cf041 5814 GEN_PRIV(ctx);
76a66253 5815#else
06dca6a7 5816 TCGv dcrn;
9b2fadda 5817
9f0cf041 5818 CHK_SV(ctx);
06dca6a7 5819 dcrn = tcg_const_tl(SPR(ctx->opcode));
d0f1562d 5820 gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]);
06dca6a7 5821 tcg_temp_free(dcrn);
9b2fadda 5822#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc
JM
5823}
5824
5825/* mfdcrx */
2662a059 5826/* XXX: not implemented on 440 ? */
99e300ef 5827static void gen_mfdcrx(DisasContext *ctx)
a42bd6cc
JM
5828{
5829#if defined(CONFIG_USER_ONLY)
9f0cf041 5830 GEN_PRIV(ctx);
a42bd6cc 5831#else
9f0cf041 5832 CHK_SV(ctx);
d0f1562d
BS
5833 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env,
5834 cpu_gpr[rA(ctx->opcode)]);
a750fc0b 5835 /* Note: Rc update flag set leads to undefined state of Rc0 */
9b2fadda 5836#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc
JM
5837}
5838
5839/* mtdcrx */
2662a059 5840/* XXX: not implemented on 440 ? */
99e300ef 5841static void gen_mtdcrx(DisasContext *ctx)
a42bd6cc
JM
5842{
5843#if defined(CONFIG_USER_ONLY)
9f0cf041 5844 GEN_PRIV(ctx);
a42bd6cc 5845#else
9f0cf041 5846 CHK_SV(ctx);
d0f1562d
BS
5847 gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)],
5848 cpu_gpr[rS(ctx->opcode)]);
a750fc0b 5849 /* Note: Rc update flag set leads to undefined state of Rc0 */
9b2fadda 5850#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5851}
5852
5853/* dccci */
99e300ef 5854static void gen_dccci(DisasContext *ctx)
76a66253 5855{
9f0cf041 5856 CHK_SV(ctx);
76a66253 5857 /* interpreted as no-op */
76a66253
JM
5858}
5859
5860/* dcread */
99e300ef 5861static void gen_dcread(DisasContext *ctx)
76a66253
JM
5862{
5863#if defined(CONFIG_USER_ONLY)
9f0cf041 5864 GEN_PRIV(ctx);
76a66253 5865#else
b61f2753 5866 TCGv EA, val;
9b2fadda 5867
9f0cf041 5868 CHK_SV(ctx);
76db3ba4 5869 gen_set_access_type(ctx, ACCESS_CACHE);
a7812ae4 5870 EA = tcg_temp_new();
76db3ba4 5871 gen_addr_reg_index(ctx, EA);
a7812ae4 5872 val = tcg_temp_new();
76db3ba4 5873 gen_qemu_ld32u(ctx, val, EA);
b61f2753
AJ
5874 tcg_temp_free(val);
5875 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5876 tcg_temp_free(EA);
9b2fadda 5877#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5878}
5879
5880/* icbt */
e8eaa2c0 5881static void gen_icbt_40x(DisasContext *ctx)
76a66253 5882{
efe843d8
DG
5883 /*
5884 * interpreted as no-op
5885 * XXX: specification say this is treated as a load by the MMU but
5886 * does not generate any exception
76a66253
JM
5887 */
5888}
5889
5890/* iccci */
99e300ef 5891static void gen_iccci(DisasContext *ctx)
76a66253 5892{
9f0cf041 5893 CHK_SV(ctx);
76a66253 5894 /* interpreted as no-op */
76a66253
JM
5895}
5896
5897/* icread */
99e300ef 5898static void gen_icread(DisasContext *ctx)
76a66253 5899{
9f0cf041 5900 CHK_SV(ctx);
76a66253 5901 /* interpreted as no-op */
76a66253
JM
5902}
5903
c47493f2 5904/* rfci (supervisor only) */
e8eaa2c0 5905static void gen_rfci_40x(DisasContext *ctx)
a42bd6cc
JM
5906{
5907#if defined(CONFIG_USER_ONLY)
9f0cf041 5908 GEN_PRIV(ctx);
a42bd6cc 5909#else
9f0cf041 5910 CHK_SV(ctx);
a42bd6cc 5911 /* Restore CPU state */
e5f17ac6 5912 gen_helper_40x_rfci(cpu_env);
59bf23fa 5913 ctx->base.is_jmp = DISAS_EXIT;
9b2fadda 5914#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc
JM
5915}
5916
99e300ef 5917static void gen_rfci(DisasContext *ctx)
a42bd6cc
JM
5918{
5919#if defined(CONFIG_USER_ONLY)
9f0cf041 5920 GEN_PRIV(ctx);
a42bd6cc 5921#else
9f0cf041 5922 CHK_SV(ctx);
a42bd6cc 5923 /* Restore CPU state */
e5f17ac6 5924 gen_helper_rfci(cpu_env);
59bf23fa 5925 ctx->base.is_jmp = DISAS_EXIT;
9b2fadda 5926#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc
JM
5927}
5928
5929/* BookE specific */
99e300ef 5930
54623277 5931/* XXX: not implemented on 440 ? */
99e300ef 5932static void gen_rfdi(DisasContext *ctx)
76a66253
JM
5933{
5934#if defined(CONFIG_USER_ONLY)
9f0cf041 5935 GEN_PRIV(ctx);
76a66253 5936#else
9f0cf041 5937 CHK_SV(ctx);
76a66253 5938 /* Restore CPU state */
e5f17ac6 5939 gen_helper_rfdi(cpu_env);
59bf23fa 5940 ctx->base.is_jmp = DISAS_EXIT;
9b2fadda 5941#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5942}
5943
2662a059 5944/* XXX: not implemented on 440 ? */
99e300ef 5945static void gen_rfmci(DisasContext *ctx)
a42bd6cc
JM
5946{
5947#if defined(CONFIG_USER_ONLY)
9f0cf041 5948 GEN_PRIV(ctx);
a42bd6cc 5949#else
9f0cf041 5950 CHK_SV(ctx);
a42bd6cc 5951 /* Restore CPU state */
e5f17ac6 5952 gen_helper_rfmci(cpu_env);
59bf23fa 5953 ctx->base.is_jmp = DISAS_EXIT;
9b2fadda 5954#endif /* defined(CONFIG_USER_ONLY) */
a42bd6cc 5955}
5eb7995e 5956
d9bce9d9 5957/* TLB management - PowerPC 405 implementation */
e8eaa2c0 5958
54623277 5959/* tlbre */
e8eaa2c0 5960static void gen_tlbre_40x(DisasContext *ctx)
76a66253
JM
5961{
5962#if defined(CONFIG_USER_ONLY)
9f0cf041 5963 GEN_PRIV(ctx);
76a66253 5964#else
9f0cf041 5965 CHK_SV(ctx);
76a66253
JM
5966 switch (rB(ctx->opcode)) {
5967 case 0:
c6c7cf05
BS
5968 gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env,
5969 cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5970 break;
5971 case 1:
c6c7cf05
BS
5972 gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env,
5973 cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5974 break;
5975 default:
e06fcd75 5976 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253 5977 break;
9a64fbe4 5978 }
9b2fadda 5979#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
5980}
5981
d9bce9d9 5982/* tlbsx - tlbsx. */
e8eaa2c0 5983static void gen_tlbsx_40x(DisasContext *ctx)
76a66253
JM
5984{
5985#if defined(CONFIG_USER_ONLY)
9f0cf041 5986 GEN_PRIV(ctx);
76a66253 5987#else
74d37793 5988 TCGv t0;
9b2fadda 5989
9f0cf041 5990 CHK_SV(ctx);
74d37793 5991 t0 = tcg_temp_new();
76db3ba4 5992 gen_addr_reg_index(ctx, t0);
c6c7cf05 5993 gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793
AJ
5994 tcg_temp_free(t0);
5995 if (Rc(ctx->opcode)) {
42a268c2 5996 TCGLabel *l1 = gen_new_label();
da91a00f 5997 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
74d37793
AJ
5998 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5999 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6000 gen_set_label(l1);
6001 }
9b2fadda 6002#endif /* defined(CONFIG_USER_ONLY) */
79aceca5
FB
6003}
6004
76a66253 6005/* tlbwe */
e8eaa2c0 6006static void gen_tlbwe_40x(DisasContext *ctx)
79aceca5 6007{
76a66253 6008#if defined(CONFIG_USER_ONLY)
9f0cf041 6009 GEN_PRIV(ctx);
76a66253 6010#else
9f0cf041 6011 CHK_SV(ctx);
9b2fadda 6012
76a66253
JM
6013 switch (rB(ctx->opcode)) {
6014 case 0:
c6c7cf05
BS
6015 gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)],
6016 cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
6017 break;
6018 case 1:
c6c7cf05
BS
6019 gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)],
6020 cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
6021 break;
6022 default:
e06fcd75 6023 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253 6024 break;
9a64fbe4 6025 }
9b2fadda 6026#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6027}
6028
a4bb6c3e 6029/* TLB management - PowerPC 440 implementation */
e8eaa2c0 6030
54623277 6031/* tlbre */
e8eaa2c0 6032static void gen_tlbre_440(DisasContext *ctx)
5eb7995e
JM
6033{
6034#if defined(CONFIG_USER_ONLY)
9f0cf041 6035 GEN_PRIV(ctx);
5eb7995e 6036#else
9f0cf041 6037 CHK_SV(ctx);
9b2fadda 6038
5eb7995e
JM
6039 switch (rB(ctx->opcode)) {
6040 case 0:
5eb7995e 6041 case 1:
5eb7995e 6042 case 2:
74d37793
AJ
6043 {
6044 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
c6c7cf05
BS
6045 gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env,
6046 t0, cpu_gpr[rA(ctx->opcode)]);
74d37793
AJ
6047 tcg_temp_free_i32(t0);
6048 }
5eb7995e
JM
6049 break;
6050 default:
e06fcd75 6051 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5eb7995e
JM
6052 break;
6053 }
9b2fadda 6054#endif /* defined(CONFIG_USER_ONLY) */
5eb7995e
JM
6055}
6056
6057/* tlbsx - tlbsx. */
e8eaa2c0 6058static void gen_tlbsx_440(DisasContext *ctx)
5eb7995e
JM
6059{
6060#if defined(CONFIG_USER_ONLY)
9f0cf041 6061 GEN_PRIV(ctx);
5eb7995e 6062#else
74d37793 6063 TCGv t0;
9b2fadda 6064
9f0cf041 6065 CHK_SV(ctx);
74d37793 6066 t0 = tcg_temp_new();
76db3ba4 6067 gen_addr_reg_index(ctx, t0);
c6c7cf05 6068 gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0);
74d37793
AJ
6069 tcg_temp_free(t0);
6070 if (Rc(ctx->opcode)) {
42a268c2 6071 TCGLabel *l1 = gen_new_label();
da91a00f 6072 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
74d37793
AJ
6073 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
6074 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
6075 gen_set_label(l1);
6076 }
9b2fadda 6077#endif /* defined(CONFIG_USER_ONLY) */
5eb7995e
JM
6078}
6079
6080/* tlbwe */
e8eaa2c0 6081static void gen_tlbwe_440(DisasContext *ctx)
5eb7995e
JM
6082{
6083#if defined(CONFIG_USER_ONLY)
9f0cf041 6084 GEN_PRIV(ctx);
5eb7995e 6085#else
9f0cf041 6086 CHK_SV(ctx);
5eb7995e
JM
6087 switch (rB(ctx->opcode)) {
6088 case 0:
5eb7995e 6089 case 1:
5eb7995e 6090 case 2:
74d37793
AJ
6091 {
6092 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
c6c7cf05
BS
6093 gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)],
6094 cpu_gpr[rS(ctx->opcode)]);
74d37793
AJ
6095 tcg_temp_free_i32(t0);
6096 }
5eb7995e
JM
6097 break;
6098 default:
e06fcd75 6099 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5eb7995e
JM
6100 break;
6101 }
9b2fadda 6102#endif /* defined(CONFIG_USER_ONLY) */
5eb7995e
JM
6103}
6104
01662f3e
AG
6105/* TLB management - PowerPC BookE 2.06 implementation */
6106
6107/* tlbre */
6108static void gen_tlbre_booke206(DisasContext *ctx)
6109{
9b2fadda 6110 #if defined(CONFIG_USER_ONLY)
9f0cf041 6111 GEN_PRIV(ctx);
01662f3e 6112#else
9f0cf041 6113 CHK_SV(ctx);
c6c7cf05 6114 gen_helper_booke206_tlbre(cpu_env);
9b2fadda 6115#endif /* defined(CONFIG_USER_ONLY) */
01662f3e
AG
6116}
6117
6118/* tlbsx - tlbsx. */
6119static void gen_tlbsx_booke206(DisasContext *ctx)
6120{
6121#if defined(CONFIG_USER_ONLY)
9f0cf041 6122 GEN_PRIV(ctx);
01662f3e
AG
6123#else
6124 TCGv t0;
01662f3e 6125
9f0cf041 6126 CHK_SV(ctx);
01662f3e
AG
6127 if (rA(ctx->opcode)) {
6128 t0 = tcg_temp_new();
6129 tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
6130 } else {
6131 t0 = tcg_const_tl(0);
6132 }
6133
6134 tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
c6c7cf05 6135 gen_helper_booke206_tlbsx(cpu_env, t0);
c80d1df5 6136 tcg_temp_free(t0);
9b2fadda 6137#endif /* defined(CONFIG_USER_ONLY) */
01662f3e
AG
6138}
6139
6140/* tlbwe */
6141static void gen_tlbwe_booke206(DisasContext *ctx)
6142{
6143#if defined(CONFIG_USER_ONLY)
9f0cf041 6144 GEN_PRIV(ctx);
01662f3e 6145#else
9f0cf041 6146 CHK_SV(ctx);
c6c7cf05 6147 gen_helper_booke206_tlbwe(cpu_env);
9b2fadda 6148#endif /* defined(CONFIG_USER_ONLY) */
01662f3e
AG
6149}
6150
6151static void gen_tlbivax_booke206(DisasContext *ctx)
6152{
6153#if defined(CONFIG_USER_ONLY)
9f0cf041 6154 GEN_PRIV(ctx);
01662f3e
AG
6155#else
6156 TCGv t0;
01662f3e 6157
9f0cf041 6158 CHK_SV(ctx);
01662f3e
AG
6159 t0 = tcg_temp_new();
6160 gen_addr_reg_index(ctx, t0);
c6c7cf05 6161 gen_helper_booke206_tlbivax(cpu_env, t0);
c80d1df5 6162 tcg_temp_free(t0);
9b2fadda 6163#endif /* defined(CONFIG_USER_ONLY) */
01662f3e
AG
6164}
6165
6d3db821
AG
6166static void gen_tlbilx_booke206(DisasContext *ctx)
6167{
6168#if defined(CONFIG_USER_ONLY)
9f0cf041 6169 GEN_PRIV(ctx);
6d3db821
AG
6170#else
6171 TCGv t0;
6d3db821 6172
9f0cf041 6173 CHK_SV(ctx);
6d3db821
AG
6174 t0 = tcg_temp_new();
6175 gen_addr_reg_index(ctx, t0);
6176
efe843d8 6177 switch ((ctx->opcode >> 21) & 0x3) {
6d3db821 6178 case 0:
c6c7cf05 6179 gen_helper_booke206_tlbilx0(cpu_env, t0);
6d3db821
AG
6180 break;
6181 case 1:
c6c7cf05 6182 gen_helper_booke206_tlbilx1(cpu_env, t0);
6d3db821
AG
6183 break;
6184 case 3:
c6c7cf05 6185 gen_helper_booke206_tlbilx3(cpu_env, t0);
6d3db821
AG
6186 break;
6187 default:
6188 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6189 break;
6190 }
6191
6192 tcg_temp_free(t0);
9b2fadda 6193#endif /* defined(CONFIG_USER_ONLY) */
6d3db821
AG
6194}
6195
76a66253 6196/* wrtee */
99e300ef 6197static void gen_wrtee(DisasContext *ctx)
76a66253
JM
6198{
6199#if defined(CONFIG_USER_ONLY)
9f0cf041 6200 GEN_PRIV(ctx);
76a66253 6201#else
6527f6ea 6202 TCGv t0;
9b2fadda 6203
9f0cf041 6204 CHK_SV(ctx);
6527f6ea
AJ
6205 t0 = tcg_temp_new();
6206 tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6207 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6208 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
2fdedcbc 6209 gen_ppc_maybe_interrupt(ctx);
6527f6ea 6210 tcg_temp_free(t0);
efe843d8
DG
6211 /*
6212 * Stop translation to have a chance to raise an exception if we
6213 * just set msr_ee to 1
dee96f6c 6214 */
d736de8f 6215 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
9b2fadda 6216#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6217}
6218
6219/* wrteei */
99e300ef 6220static void gen_wrteei(DisasContext *ctx)
76a66253
JM
6221{
6222#if defined(CONFIG_USER_ONLY)
9f0cf041 6223 GEN_PRIV(ctx);
76a66253 6224#else
9f0cf041 6225 CHK_SV(ctx);
fbe73008 6226 if (ctx->opcode & 0x00008000) {
6527f6ea 6227 tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
2fdedcbc 6228 gen_ppc_maybe_interrupt(ctx);
6527f6ea 6229 /* Stop translation to have a chance to raise an exception */
d736de8f 6230 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
6527f6ea 6231 } else {
1b6e5f99 6232 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6527f6ea 6233 }
9b2fadda 6234#endif /* defined(CONFIG_USER_ONLY) */
76a66253
JM
6235}
6236
08e46e54 6237/* PowerPC 440 specific instructions */
99e300ef 6238
54623277 6239/* dlmzb */
99e300ef 6240static void gen_dlmzb(DisasContext *ctx)
76a66253 6241{
ef0d51af 6242 TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
d15f74fb
BS
6243 gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env,
6244 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
ef0d51af 6245 tcg_temp_free_i32(t0);
76a66253
JM
6246}
6247
6248/* mbar replaces eieio on 440 */
99e300ef 6249static void gen_mbar(DisasContext *ctx)
76a66253
JM
6250{
6251 /* interpreted as no-op */
6252}
6253
6254/* msync replaces sync on 440 */
dcb2b9e1 6255static void gen_msync_4xx(DisasContext *ctx)
76a66253 6256{
27a3ea7e
BZ
6257 /* Only e500 seems to treat reserved bits as invalid */
6258 if ((ctx->insns_flags2 & PPC2_BOOKE206) &&
6259 (ctx->opcode & 0x03FFF801)) {
6260 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
6261 }
6262 /* otherwise interpreted as no-op */
76a66253
JM
6263}
6264
6265/* icbt */
e8eaa2c0 6266static void gen_icbt_440(DisasContext *ctx)
76a66253 6267{
efe843d8
DG
6268 /*
6269 * interpreted as no-op
6270 * XXX: specification say this is treated as a load by the MMU but
6271 * does not generate any exception
76a66253 6272 */
79aceca5
FB
6273}
6274
aeeb044c
ND
6275#if defined(TARGET_PPC64)
6276static void gen_maddld(DisasContext *ctx)
6277{
6278 TCGv_i64 t1 = tcg_temp_new_i64();
6279
6280 tcg_gen_mul_i64(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6281 tcg_gen_add_i64(cpu_gpr[rD(ctx->opcode)], t1, cpu_gpr[rC(ctx->opcode)]);
6282 tcg_temp_free_i64(t1);
6283}
5f29cc82
ND
6284
6285/* maddhd maddhdu */
6286static void gen_maddhd_maddhdu(DisasContext *ctx)
6287{
6288 TCGv_i64 lo = tcg_temp_new_i64();
6289 TCGv_i64 hi = tcg_temp_new_i64();
6290 TCGv_i64 t1 = tcg_temp_new_i64();
6291
6292 if (Rc(ctx->opcode)) {
6293 tcg_gen_mulu2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)],
6294 cpu_gpr[rB(ctx->opcode)]);
6295 tcg_gen_movi_i64(t1, 0);
6296 } else {
6297 tcg_gen_muls2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)],
6298 cpu_gpr[rB(ctx->opcode)]);
6299 tcg_gen_sari_i64(t1, cpu_gpr[rC(ctx->opcode)], 63);
6300 }
6301 tcg_gen_add2_i64(t1, cpu_gpr[rD(ctx->opcode)], lo, hi,
6302 cpu_gpr[rC(ctx->opcode)], t1);
6303 tcg_temp_free_i64(lo);
6304 tcg_temp_free_i64(hi);
6305 tcg_temp_free_i64(t1);
6306}
aeeb044c
ND
6307#endif /* defined(TARGET_PPC64) */
6308
0ff93d11
TM
6309static void gen_tbegin(DisasContext *ctx)
6310{
6311 if (unlikely(!ctx->tm_enabled)) {
6312 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
6313 return;
6314 }
6315 gen_helper_tbegin(cpu_env);
6316}
6317
56a84615
TM
6318#define GEN_TM_NOOP(name) \
6319static inline void gen_##name(DisasContext *ctx) \
6320{ \
6321 if (unlikely(!ctx->tm_enabled)) { \
6322 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
6323 return; \
6324 } \
efe843d8
DG
6325 /* \
6326 * Because tbegin always fails in QEMU, these user \
56a84615
TM
6327 * space instructions all have a simple implementation: \
6328 * \
6329 * CR[0] = 0b0 || MSR[TS] || 0b0 \
6330 * = 0b0 || 0b00 || 0b0 \
6331 */ \
6332 tcg_gen_movi_i32(cpu_crf[0], 0); \
6333}
6334
6335GEN_TM_NOOP(tend);
6336GEN_TM_NOOP(tabort);
6337GEN_TM_NOOP(tabortwc);
6338GEN_TM_NOOP(tabortwci);
6339GEN_TM_NOOP(tabortdc);
6340GEN_TM_NOOP(tabortdci);
6341GEN_TM_NOOP(tsr);
efe843d8 6342
b8b4576e
SJS
6343static inline void gen_cp_abort(DisasContext *ctx)
6344{
efe843d8 6345 /* Do Nothing */
b8b4576e 6346}
56a84615 6347
80b8c1ee
ND
6348#define GEN_CP_PASTE_NOOP(name) \
6349static inline void gen_##name(DisasContext *ctx) \
6350{ \
efe843d8
DG
6351 /* \
6352 * Generate invalid exception until we have an \
6353 * implementation of the copy paste facility \
80b8c1ee
ND
6354 */ \
6355 gen_invalid(ctx); \
6356}
6357
6358GEN_CP_PASTE_NOOP(copy)
6359GEN_CP_PASTE_NOOP(paste)
6360
aeedd582
TM
6361static void gen_tcheck(DisasContext *ctx)
6362{
6363 if (unlikely(!ctx->tm_enabled)) {
6364 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
6365 return;
6366 }
efe843d8
DG
6367 /*
6368 * Because tbegin always fails, the tcheck implementation is
6369 * simple:
aeedd582
TM
6370 *
6371 * CR[CRF] = TDOOMED || MSR[TS] || 0b0
6372 * = 0b1 || 0b00 || 0b0
6373 */
6374 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0x8);
6375}
6376
f83c2378
TM
6377#if defined(CONFIG_USER_ONLY)
6378#define GEN_TM_PRIV_NOOP(name) \
6379static inline void gen_##name(DisasContext *ctx) \
6380{ \
9f0cf041 6381 gen_priv_opc(ctx); \
f83c2378
TM
6382}
6383
6384#else
6385
6386#define GEN_TM_PRIV_NOOP(name) \
6387static inline void gen_##name(DisasContext *ctx) \
6388{ \
9f0cf041 6389 CHK_SV(ctx); \
f83c2378
TM
6390 if (unlikely(!ctx->tm_enabled)) { \
6391 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
6392 return; \
6393 } \
efe843d8
DG
6394 /* \
6395 * Because tbegin always fails, the implementation is \
f83c2378
TM
6396 * simple: \
6397 * \
6398 * CR[0] = 0b0 || MSR[TS] || 0b0 \
6399 * = 0b0 || 0b00 | 0b0 \
6400 */ \
6401 tcg_gen_movi_i32(cpu_crf[0], 0); \
6402}
6403
6404#endif
6405
6406GEN_TM_PRIV_NOOP(treclaim);
6407GEN_TM_PRIV_NOOP(trechkpt);
6408
1a404c91
MCA
6409static inline void get_fpr(TCGv_i64 dst, int regno)
6410{
e7d3b272 6411 tcg_gen_ld_i64(dst, cpu_env, fpr_offset(regno));
1a404c91
MCA
6412}
6413
6414static inline void set_fpr(int regno, TCGv_i64 src)
6415{
e7d3b272 6416 tcg_gen_st_i64(src, cpu_env, fpr_offset(regno));
4b65b6e7
VC
6417 /*
6418 * Before PowerISA v3.1 the result of doubleword 1 of the VSR
6419 * corresponding to the target FPR was undefined. However,
6420 * most (if not all) real hardware were setting the result to 0.
6421 * Starting at ISA v3.1, the result for doubleword 1 is now defined
6422 * to be 0.
6423 */
6424 tcg_gen_st_i64(tcg_constant_i64(0), cpu_env, vsr64_offset(regno, false));
1a404c91
MCA
6425}
6426
c4a18dbf
MCA
6427static inline void get_avr64(TCGv_i64 dst, int regno, bool high)
6428{
37da91f1 6429 tcg_gen_ld_i64(dst, cpu_env, avr64_offset(regno, high));
c4a18dbf
MCA
6430}
6431
6432static inline void set_avr64(int regno, TCGv_i64 src, bool high)
6433{
37da91f1 6434 tcg_gen_st_i64(src, cpu_env, avr64_offset(regno, high));
c4a18dbf
MCA
6435}
6436
f2aabda8
RH
6437/*
6438 * Helpers for decodetree used by !function for decoding arguments.
6439 */
d39b2cc7
LP
6440static int times_2(DisasContext *ctx, int x)
6441{
6442 return x * 2;
6443}
6444
f2aabda8
RH
6445static int times_4(DisasContext *ctx, int x)
6446{
6447 return x * 4;
6448}
6449
e10271e1
MF
6450static int times_16(DisasContext *ctx, int x)
6451{
6452 return x * 16;
6453}
6454
670f1da3
VC
6455static int64_t dw_compose_ea(DisasContext *ctx, int x)
6456{
6457 return deposit64(0xfffffffffffffe00, 3, 6, x);
6458}
6459
c9826ae9
RH
6460/*
6461 * Helpers for trans_* functions to check for specific insns flags.
6462 * Use token pasting to ensure that we use the proper flag with the
6463 * proper variable.
6464 */
6465#define REQUIRE_INSNS_FLAGS(CTX, NAME) \
6466 do { \
6467 if (((CTX)->insns_flags & PPC_##NAME) == 0) { \
6468 return false; \
6469 } \
6470 } while (0)
6471
6472#define REQUIRE_INSNS_FLAGS2(CTX, NAME) \
6473 do { \
6474 if (((CTX)->insns_flags2 & PPC2_##NAME) == 0) { \
6475 return false; \
6476 } \
6477 } while (0)
6478
6479/* Then special-case the check for 64-bit so that we elide code for ppc32. */
6480#if TARGET_LONG_BITS == 32
6481# define REQUIRE_64BIT(CTX) return false
6482#else
6483# define REQUIRE_64BIT(CTX) REQUIRE_INSNS_FLAGS(CTX, 64B)
6484#endif
6485
e2205a46
BL
6486#define REQUIRE_VECTOR(CTX) \
6487 do { \
6488 if (unlikely(!(CTX)->altivec_enabled)) { \
6489 gen_exception((CTX), POWERPC_EXCP_VPU); \
6490 return true; \
6491 } \
8226cb2d
BL
6492 } while (0)
6493
6494#define REQUIRE_VSX(CTX) \
6495 do { \
6496 if (unlikely(!(CTX)->vsx_enabled)) { \
6497 gen_exception((CTX), POWERPC_EXCP_VSXU); \
6498 return true; \
6499 } \
e2205a46
BL
6500 } while (0)
6501
86057426
FV
6502#define REQUIRE_FPU(ctx) \
6503 do { \
6504 if (unlikely(!(ctx)->fpu_enabled)) { \
6505 gen_exception((ctx), POWERPC_EXCP_FPU); \
6506 return true; \
6507 } \
6508 } while (0)
6509
fc34e81a
MF
6510#if !defined(CONFIG_USER_ONLY)
6511#define REQUIRE_SV(CTX) \
6512 do { \
6513 if (unlikely((CTX)->pr)) { \
6514 gen_priv_opc(CTX); \
6515 return true; \
6516 } \
6517 } while (0)
6518
e8db3cc7
MF
6519#define REQUIRE_HV(CTX) \
6520 do { \
6521 if (unlikely((CTX)->pr || !(CTX)->hv)) { \
6522 gen_priv_opc(CTX); \
6523 return true; \
6524 } \
fc34e81a
MF
6525 } while (0)
6526#else
6527#define REQUIRE_SV(CTX) do { gen_priv_opc(CTX); return true; } while (0)
6528#define REQUIRE_HV(CTX) do { gen_priv_opc(CTX); return true; } while (0)
6529#endif
6530
f2aabda8
RH
6531/*
6532 * Helpers for implementing sets of trans_* functions.
6533 * Defer the implementation of NAME to FUNC, with optional extra arguments.
6534 */
6535#define TRANS(NAME, FUNC, ...) \
6536 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6537 { return FUNC(ctx, a, __VA_ARGS__); }
19f0862d
LP
6538#define TRANS_FLAGS(FLAGS, NAME, FUNC, ...) \
6539 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6540 { \
6541 REQUIRE_INSNS_FLAGS(ctx, FLAGS); \
6542 return FUNC(ctx, a, __VA_ARGS__); \
6543 }
6544#define TRANS_FLAGS2(FLAGS2, NAME, FUNC, ...) \
6545 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6546 { \
6547 REQUIRE_INSNS_FLAGS2(ctx, FLAGS2); \
6548 return FUNC(ctx, a, __VA_ARGS__); \
6549 }
f2aabda8
RH
6550
6551#define TRANS64(NAME, FUNC, ...) \
6552 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6553 { REQUIRE_64BIT(ctx); return FUNC(ctx, a, __VA_ARGS__); }
19f0862d
LP
6554#define TRANS64_FLAGS2(FLAGS2, NAME, FUNC, ...) \
6555 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
6556 { \
6557 REQUIRE_64BIT(ctx); \
6558 REQUIRE_INSNS_FLAGS2(ctx, FLAGS2); \
6559 return FUNC(ctx, a, __VA_ARGS__); \
6560 }
f2aabda8
RH
6561
6562/* TODO: More TRANS* helpers for extra insn_flags checks. */
6563
6564
99082815
RH
6565#include "decode-insn32.c.inc"
6566#include "decode-insn64.c.inc"
565cb109
GR
6567#include "power8-pmu-regs.c.inc"
6568
725b2d4d
FEV
6569/*
6570 * Incorporate CIA into the constant when R=1.
6571 * Validate that when R=1, RA=0.
6572 */
6573static bool resolve_PLS_D(DisasContext *ctx, arg_D *d, arg_PLS_D *a)
6574{
6575 d->rt = a->rt;
6576 d->ra = a->ra;
6577 d->si = a->si;
6578 if (a->r) {
6579 if (unlikely(a->ra != 0)) {
6580 gen_invalid(ctx);
6581 return false;
6582 }
6583 d->si += ctx->cia;
6584 }
6585 return true;
6586}
6587
99082815
RH
6588#include "translate/fixedpoint-impl.c.inc"
6589
139c1837 6590#include "translate/fp-impl.c.inc"
15848410 6591
139c1837 6592#include "translate/vmx-impl.c.inc"
15848410 6593
139c1837 6594#include "translate/vsx-impl.c.inc"
15848410 6595
139c1837 6596#include "translate/dfp-impl.c.inc"
15848410 6597
139c1837 6598#include "translate/spe-impl.c.inc"
15848410 6599
1f26c751
DHB
6600#include "translate/branch-impl.c.inc"
6601
98f43417
MF
6602#include "translate/processor-ctrl-impl.c.inc"
6603
016b6e1d
LL
6604#include "translate/storage-ctrl-impl.c.inc"
6605
20e2d04e 6606/* Handles lfdp */
5cb091a4
ND
6607static void gen_dform39(DisasContext *ctx)
6608{
20e2d04e 6609 if ((ctx->opcode & 0x3) == 0) {
5cb091a4
ND
6610 if (ctx->insns_flags2 & PPC2_ISA205) {
6611 return gen_lfdp(ctx);
6612 }
5cb091a4
ND
6613 }
6614 return gen_invalid(ctx);
6615}
6616
20e2d04e 6617/* Handles stfdp */
e3001664
ND
6618static void gen_dform3D(DisasContext *ctx)
6619{
20e2d04e
LL
6620 if ((ctx->opcode & 3) == 0) { /* DS-FORM */
6621 /* stfdp */
6622 if (ctx->insns_flags2 & PPC2_ISA205) {
6623 return gen_stfdp(ctx);
e3001664
ND
6624 }
6625 }
6626 return gen_invalid(ctx);
6627}
6628
9d69cfa2
LP
6629#if defined(TARGET_PPC64)
6630/* brd */
6631static void gen_brd(DisasContext *ctx)
6632{
6633 tcg_gen_bswap64_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
6634}
6635
6636/* brw */
6637static void gen_brw(DisasContext *ctx)
6638{
6639 tcg_gen_bswap64_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
6640 tcg_gen_rotli_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 32);
6641
6642}
6643
6644/* brh */
6645static void gen_brh(DisasContext *ctx)
6646{
491b3cca 6647 TCGv_i64 mask = tcg_constant_i64(0x00ff00ff00ff00ffull);
9d69cfa2
LP
6648 TCGv_i64 t1 = tcg_temp_new_i64();
6649 TCGv_i64 t2 = tcg_temp_new_i64();
6650
9d69cfa2 6651 tcg_gen_shri_i64(t1, cpu_gpr[rS(ctx->opcode)], 8);
491b3cca
PMD
6652 tcg_gen_and_i64(t2, t1, mask);
6653 tcg_gen_and_i64(t1, cpu_gpr[rS(ctx->opcode)], mask);
9d69cfa2
LP
6654 tcg_gen_shli_i64(t1, t1, 8);
6655 tcg_gen_or_i64(cpu_gpr[rA(ctx->opcode)], t1, t2);
6656
9d69cfa2
LP
6657 tcg_temp_free_i64(t1);
6658 tcg_temp_free_i64(t2);
6659}
6660#endif
6661
c227f099 6662static opcode_t opcodes[] = {
9d69cfa2
LP
6663#if defined(TARGET_PPC64)
6664GEN_HANDLER_E(brd, 0x1F, 0x1B, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA310),
6665GEN_HANDLER_E(brw, 0x1F, 0x1B, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA310),
6666GEN_HANDLER_E(brh, 0x1F, 0x1B, 0x06, 0x0000F801, PPC_NONE, PPC2_ISA310),
6667#endif
5c55ff99 6668GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
082ce330
ND
6669#if defined(TARGET_PPC64)
6670GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300),
6671#endif
fcfda20f 6672GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
f2442ef9 6673GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x00400001, PPC_NONE, PPC2_ISA300),
5c55ff99 6674GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
5c55ff99
BS
6675GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6676GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
5c55ff99
BS
6677GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
6678GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
6679GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
6680GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
6681GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6682#if defined(TARGET_PPC64)
6683GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
6684#endif
6685GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
6686GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
6687GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6688GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6689GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6690GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
b35344e4 6691GEN_HANDLER_E(cnttzw, 0x1F, 0x1A, 0x10, 0x00000000, PPC_NONE, PPC2_ISA300),
80b8c1ee 6692GEN_HANDLER_E(copy, 0x1F, 0x06, 0x18, 0x03C00001, PPC_NONE, PPC2_ISA300),
b8b4576e 6693GEN_HANDLER_E(cp_abort, 0x1F, 0x06, 0x1A, 0x03FFF801, PPC_NONE, PPC2_ISA300),
80b8c1ee 6694GEN_HANDLER_E(paste, 0x1F, 0x06, 0x1C, 0x03C00000, PPC_NONE, PPC2_ISA300),
5c55ff99
BS
6695GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
6696GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
6697GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6698GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6699GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6700GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6ab39b1b 6701GEN_HANDLER(popcntb, 0x1F, 0x1A, 0x03, 0x0000F801, PPC_POPCNTB),
eaabeef2 6702GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
725bcec2 6703GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
5c55ff99 6704#if defined(TARGET_PPC64)
eaabeef2 6705GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
5c55ff99 6706GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
e91d95b2 6707GEN_HANDLER_E(cnttzd, 0x1F, 0x1A, 0x11, 0x00000000, PPC_NONE, PPC2_ISA300),
fec5c62a 6708GEN_HANDLER_E(darn, 0x1F, 0x13, 0x17, 0x001CF801, PPC_NONE, PPC2_ISA300),
725bcec2 6709GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
86ba37ed 6710GEN_HANDLER_E(bpermd, 0x1F, 0x1C, 0x07, 0x00000001, PPC_NONE, PPC2_PERM_ISA206),
5c55ff99
BS
6711#endif
6712GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6713GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6714GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6715GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
6716GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
6717GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
6718GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
6719#if defined(TARGET_PPC64)
6720GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
6721GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
6722GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
6723GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
6724GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
787bbe37
ND
6725GEN_HANDLER2_E(extswsli0, "extswsli", 0x1F, 0x1A, 0x1B, 0x00000000,
6726 PPC_NONE, PPC2_ISA300),
6727GEN_HANDLER2_E(extswsli1, "extswsli", 0x1F, 0x1B, 0x1B, 0x00000000,
6728 PPC_NONE, PPC2_ISA300),
5c55ff99 6729#endif
5cb091a4
ND
6730/* handles lfdp, lxsd, lxssp */
6731GEN_HANDLER_E(dform39, 0x39, 0xFF, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA205),
72b70d5c 6732/* handles stfdp, stxsd, stxssp */
e3001664 6733GEN_HANDLER_E(dform3D, 0x3D, 0xFF, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA205),
5c55ff99
BS
6734GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6735GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
6736GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
6737GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
6738GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
6739GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
c8fd8373 6740GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x01FFF801, PPC_MEM_EIEIO),
5c55ff99 6741GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
5c77a786
TM
6742GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
6743GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
f844c817 6744GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
a68a6146 6745GEN_HANDLER_E(lwat, 0x1F, 0x06, 0x12, 0x00000001, PPC_NONE, PPC2_ISA300),
a3401188 6746GEN_HANDLER_E(stwat, 0x1F, 0x06, 0x16, 0x00000001, PPC_NONE, PPC2_ISA300),
587c51f7
TM
6747GEN_HANDLER_E(stbcx_, 0x1F, 0x16, 0x15, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
6748GEN_HANDLER_E(sthcx_, 0x1F, 0x16, 0x16, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
5c55ff99
BS
6749GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
6750#if defined(TARGET_PPC64)
a68a6146 6751GEN_HANDLER_E(ldat, 0x1F, 0x06, 0x13, 0x00000001, PPC_NONE, PPC2_ISA300),
a3401188 6752GEN_HANDLER_E(stdat, 0x1F, 0x06, 0x17, 0x00000001, PPC_NONE, PPC2_ISA300),
f844c817 6753GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
9c294d5a 6754GEN_HANDLER_E(lqarx, 0x1F, 0x14, 0x08, 0, PPC_NONE, PPC2_LSQ_ISA207),
5c55ff99 6755GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
27b95bfe 6756GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207),
5c55ff99
BS
6757#endif
6758GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
0c9717ff
NP
6759/* ISA v3.0 changed the extended opcode from 62 to 30 */
6760GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x039FF801, PPC_WAIT),
6761GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039CF801, PPC_NONE, PPC2_ISA300),
5c55ff99
BS
6762GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
6763GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
6764GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
6765GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
4aaefd93 6766GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0x0000E000, PPC_NONE, PPC2_BCTAR_ISA207),
5c55ff99
BS
6767GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
6768GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
6769#if defined(TARGET_PPC64)
6770GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
3c89b8d6
NP
6771#if !defined(CONFIG_USER_ONLY)
6772/* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
6773GEN_HANDLER_E(scv, 0x11, 0x10, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
6774GEN_HANDLER_E(scv, 0x11, 0x00, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
6775GEN_HANDLER_E(rfscv, 0x13, 0x12, 0x02, 0x03FF8001, PPC_NONE, PPC2_ISA300),
6776#endif
cdee0e72 6777GEN_HANDLER_E(stop, 0x13, 0x12, 0x0b, 0x03FFF801, PPC_NONE, PPC2_ISA300),
7778a575
BH
6778GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
6779GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
6780GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
6781GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
5c55ff99
BS
6782GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
6783#endif
3c89b8d6
NP
6784/* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
6785GEN_HANDLER(sc, 0x11, 0x11, 0xFF, 0x03FFF01D, PPC_FLOW),
6786GEN_HANDLER(sc, 0x11, 0x01, 0xFF, 0x03FFF01D, PPC_FLOW),
5c55ff99
BS
6787GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
6788GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
6789#if defined(TARGET_PPC64)
6790GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
6791GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
6792#endif
6793GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
6794GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
6795GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
6796GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
6797GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
6798GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
6799#if defined(TARGET_PPC64)
6800GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
dc2ee038 6801GEN_HANDLER_E(setb, 0x1F, 0x00, 0x04, 0x0003F801, PPC_NONE, PPC2_ISA300),
b63d0434 6802GEN_HANDLER_E(mcrxrx, 0x1F, 0x00, 0x12, 0x007FF801, PPC_NONE, PPC2_ISA300),
5c55ff99 6803#endif
5e31867f 6804GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001EF801, PPC_MISC),
4248b336 6805GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000000, PPC_MISC),
5c55ff99 6806GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
50728199 6807GEN_HANDLER_E(dcbfep, 0x1F, 0x1F, 0x03, 0x03C00001, PPC_NONE, PPC2_BOOKE206),
5c55ff99
BS
6808GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
6809GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
50728199 6810GEN_HANDLER_E(dcbstep, 0x1F, 0x1F, 0x01, 0x03E00001, PPC_NONE, PPC2_BOOKE206),
3f34cf91 6811GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE),
50728199 6812GEN_HANDLER_E(dcbtep, 0x1F, 0x1F, 0x09, 0x00000001, PPC_NONE, PPC2_BOOKE206),
3f34cf91 6813GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
50728199 6814GEN_HANDLER_E(dcbtstep, 0x1F, 0x1F, 0x07, 0x00000001, PPC_NONE, PPC2_BOOKE206),
4d09d529 6815GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
8e33944f 6816GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
50728199 6817GEN_HANDLER_E(dcbzep, 0x1F, 0x1F, 0x1F, 0x03C00001, PPC_NONE, PPC2_BOOKE206),
5c55ff99 6818GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
99d45f8f 6819GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x01800001, PPC_ALTIVEC),
5c55ff99
BS
6820GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
6821GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
50728199 6822GEN_HANDLER_E(icbiep, 0x1F, 0x1F, 0x1E, 0x03E00001, PPC_NONE, PPC2_BOOKE206),
5c55ff99
BS
6823GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
6824GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
6825GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
6826GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
6827GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
6828#if defined(TARGET_PPC64)
6829GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
6830GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
6831 PPC_SEGMENT_64B),
6832GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
6833GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
6834 PPC_SEGMENT_64B),
5c55ff99
BS
6835#endif
6836GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
efe843d8
DG
6837/*
6838 * XXX Those instructions will need to be handled differently for
6839 * different ISA versions
6840 */
5c55ff99 6841GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
5c55ff99
BS
6842GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
6843GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
5c55ff99
BS
6844GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
6845GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
5c55ff99
BS
6846GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
6847GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
6848GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
6849GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
6850GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
6851GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
5c55ff99
BS
6852GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
6853GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
6854GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
6855GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
6856GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
6857GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
01662f3e 6858GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
5c55ff99
BS
6859GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
6860GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
6861GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
6862GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
6863GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
6864GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
6865GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
6866GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
01662f3e
AG
6867GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
6868 PPC_NONE, PPC2_BOOKE206),
6869GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
6870 PPC_NONE, PPC2_BOOKE206),
6871GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
6872 PPC_NONE, PPC2_BOOKE206),
6873GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
6874 PPC_NONE, PPC2_BOOKE206),
6d3db821
AG
6875GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
6876 PPC_NONE, PPC2_BOOKE206),
5c55ff99 6877GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
fbe73008 6878GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
5c55ff99 6879GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
01662f3e
AG
6880GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
6881 PPC_BOOKE, PPC2_BOOKE206),
27a3ea7e 6882GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x039FF801, PPC_BOOKE),
01662f3e
AG
6883GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
6884 PPC_BOOKE, PPC2_BOOKE206),
0c8d8c8b 6885GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x06, 0x08, 0x03E00001,
27a3ea7e 6886 PPC_440_SPEC),
5c55ff99
BS
6887GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
6888GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
6889GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
6890GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
aeeb044c 6891#if defined(TARGET_PPC64)
5f29cc82
ND
6892GEN_HANDLER_E(maddhd_maddhdu, 0x04, 0x18, 0xFF, 0x00000000, PPC_NONE,
6893 PPC2_ISA300),
aeeb044c
ND
6894GEN_HANDLER_E(maddld, 0x04, 0x19, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300),
6895#endif
5c55ff99
BS
6896
6897#undef GEN_INT_ARITH_ADD
6898#undef GEN_INT_ARITH_ADD_CONST
6899#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
6900GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
6901#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
6902 add_ca, compute_ca, compute_ov) \
6903GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
6904GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
6905GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
6906GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
6907GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
6908GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
6909GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
6910GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
6911GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
4c5920af 6912GEN_HANDLER_E(addex, 0x1F, 0x0A, 0x05, 0x00000000, PPC_NONE, PPC2_ISA300),
5c55ff99
BS
6913GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
6914GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
6915
6916#undef GEN_INT_ARITH_DIVW
6917#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
6918GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
6919GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
6920GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
6921GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
6922GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
a98eb9e9
TM
6923GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6924GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6a4fda33
TM
6925GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
6926GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
af2c6620
ND
6927GEN_HANDLER_E(modsw, 0x1F, 0x0B, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300),
6928GEN_HANDLER_E(moduw, 0x1F, 0x0B, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300),
5c55ff99
BS
6929
6930#if defined(TARGET_PPC64)
6931#undef GEN_INT_ARITH_DIVD
6932#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
6933GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
6934GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
6935GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
6936GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
6937GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
6938
98d1eb27
TM
6939GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
6940GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
e44259b6
TM
6941GEN_HANDLER_E(divde, 0x1F, 0x09, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
6942GEN_HANDLER_E(divdeo, 0x1F, 0x09, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
063cf14f
ND
6943GEN_HANDLER_E(modsd, 0x1F, 0x09, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300),
6944GEN_HANDLER_E(modud, 0x1F, 0x09, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300),
98d1eb27 6945
5c55ff99
BS
6946#undef GEN_INT_ARITH_MUL_HELPER
6947#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
6948GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
6949GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
6950GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
6951GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
6952#endif
6953
6954#undef GEN_INT_ARITH_SUBF
6955#undef GEN_INT_ARITH_SUBF_CONST
6956#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
6957GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
6958#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
6959 add_ca, compute_ca, compute_ov) \
6960GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
6961GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
6962GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
6963GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
6964GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
6965GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
6966GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
6967GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
6968GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
6969GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
6970GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
6971
6972#undef GEN_LOGICAL1
6973#undef GEN_LOGICAL2
6974#define GEN_LOGICAL2(name, tcg_op, opc, type) \
6975GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
6976#define GEN_LOGICAL1(name, tcg_op, opc, type) \
6977GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
6978GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
6979GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
6980GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
6981GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
6982GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
6983GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
6984GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
6985GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
6986#if defined(TARGET_PPC64)
6987GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
6988#endif
6989
6990#if defined(TARGET_PPC64)
6991#undef GEN_PPC64_R2
6992#undef GEN_PPC64_R4
6993#define GEN_PPC64_R2(name, opc1, opc2) \
6994GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
6995GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
6996 PPC_64B)
6997#define GEN_PPC64_R4(name, opc1, opc2) \
6998GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
6999GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
7000 PPC_64B), \
7001GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
7002 PPC_64B), \
7003GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
7004 PPC_64B)
7005GEN_PPC64_R4(rldicl, 0x1E, 0x00),
7006GEN_PPC64_R4(rldicr, 0x1E, 0x02),
7007GEN_PPC64_R4(rldic, 0x1E, 0x04),
7008GEN_PPC64_R2(rldcl, 0x1E, 0x08),
7009GEN_PPC64_R2(rldcr, 0x1E, 0x09),
7010GEN_PPC64_R4(rldimi, 0x1E, 0x06),
7011#endif
7012
cd6e9320 7013#undef GEN_LDX_E
b7815375 7014#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk) \
cd6e9320 7015GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
f2aabda8 7016
5c55ff99 7017#if defined(TARGET_PPC64)
ff5f3981 7018GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE)
b7815375
BH
7019
7020/* HV/P7 and later only */
4f364fe7 7021GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST)
b7815375
BH
7022GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x18, PPC_CILDST)
7023GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST)
7024GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST)
5c55ff99
BS
7025#endif
7026GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
7027GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
7028
50728199
RK
7029/* External PID based load */
7030#undef GEN_LDEPX
7031#define GEN_LDEPX(name, ldop, opc2, opc3) \
7032GEN_HANDLER_E(name##epx, 0x1F, opc2, opc3, \
7033 0x00000001, PPC_NONE, PPC2_BOOKE206),
7034
7035GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02)
7036GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08)
7037GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00)
7038#if defined(TARGET_PPC64)
fc313c64 7039GEN_LDEPX(ld, DEF_MEMOP(MO_UQ), 0x1D, 0x00)
50728199
RK
7040#endif
7041
cd6e9320 7042#undef GEN_STX_E
b7815375 7043#define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk) \
0123d3cb 7044GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000000, type, type2),
e8f4c8d6 7045
5c55ff99 7046#if defined(TARGET_PPC64)
804108aa 7047GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE)
2468f23d 7048GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST)
b7815375
BH
7049GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST)
7050GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST)
7051GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST)
5c55ff99
BS
7052#endif
7053GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
7054GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
7055
50728199
RK
7056#undef GEN_STEPX
7057#define GEN_STEPX(name, ldop, opc2, opc3) \
7058GEN_HANDLER_E(name##epx, 0x1F, opc2, opc3, \
7059 0x00000001, PPC_NONE, PPC2_BOOKE206),
7060
7061GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06)
7062GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C)
7063GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04)
7064#if defined(TARGET_PPC64)
fc313c64 7065GEN_STEPX(std, DEF_MEMOP(MO_UQ), 0x1D, 0x04)
50728199
RK
7066#endif
7067
5c55ff99
BS
7068#undef GEN_CRLOGIC
7069#define GEN_CRLOGIC(name, tcg_op, opc) \
7070GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
7071GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
7072GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
7073GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
7074GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
7075GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
7076GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
7077GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
7078GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
7079
7080#undef GEN_MAC_HANDLER
7081#define GEN_MAC_HANDLER(name, opc2, opc3) \
7082GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
7083GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
7084GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
7085GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
7086GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
7087GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
7088GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
7089GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
7090GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
7091GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
7092GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
7093GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
7094GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
7095GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
7096GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
7097GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
7098GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
7099GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
7100GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
7101GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
7102GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
7103GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
7104GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
7105GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
7106GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
7107GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
7108GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
7109GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
7110GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
7111GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
7112GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
7113GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
7114GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
7115GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
7116GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
7117GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
7118GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
7119GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
7120GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
7121GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
7122GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
7123GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
7124GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
7125
0ff93d11
TM
7126GEN_HANDLER2_E(tbegin, "tbegin", 0x1F, 0x0E, 0x14, 0x01DFF800, \
7127 PPC_NONE, PPC2_TM),
56a84615
TM
7128GEN_HANDLER2_E(tend, "tend", 0x1F, 0x0E, 0x15, 0x01FFF800, \
7129 PPC_NONE, PPC2_TM),
7130GEN_HANDLER2_E(tabort, "tabort", 0x1F, 0x0E, 0x1C, 0x03E0F800, \
7131 PPC_NONE, PPC2_TM),
7132GEN_HANDLER2_E(tabortwc, "tabortwc", 0x1F, 0x0E, 0x18, 0x00000000, \
7133 PPC_NONE, PPC2_TM),
7134GEN_HANDLER2_E(tabortwci, "tabortwci", 0x1F, 0x0E, 0x1A, 0x00000000, \
7135 PPC_NONE, PPC2_TM),
7136GEN_HANDLER2_E(tabortdc, "tabortdc", 0x1F, 0x0E, 0x19, 0x00000000, \
7137 PPC_NONE, PPC2_TM),
7138GEN_HANDLER2_E(tabortdci, "tabortdci", 0x1F, 0x0E, 0x1B, 0x00000000, \
7139 PPC_NONE, PPC2_TM),
7140GEN_HANDLER2_E(tsr, "tsr", 0x1F, 0x0E, 0x17, 0x03DFF800, \
7141 PPC_NONE, PPC2_TM),
aeedd582
TM
7142GEN_HANDLER2_E(tcheck, "tcheck", 0x1F, 0x0E, 0x16, 0x007FF800, \
7143 PPC_NONE, PPC2_TM),
f83c2378
TM
7144GEN_HANDLER2_E(treclaim, "treclaim", 0x1F, 0x0E, 0x1D, 0x03E0F800, \
7145 PPC_NONE, PPC2_TM),
7146GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \
7147 PPC_NONE, PPC2_TM),
15848410 7148
139c1837 7149#include "translate/fp-ops.c.inc"
15848410 7150
139c1837 7151#include "translate/vmx-ops.c.inc"
15848410 7152
139c1837 7153#include "translate/vsx-ops.c.inc"
15848410 7154
139c1837 7155#include "translate/spe-ops.c.inc"
5c55ff99
BS
7156};
7157
7468e2c8
BL
7158/*****************************************************************************/
7159/* Opcode types */
7160enum {
7161 PPC_DIRECT = 0, /* Opcode routine */
7162 PPC_INDIRECT = 1, /* Indirect opcode table */
7163};
7164
7165#define PPC_OPCODE_MASK 0x3
7166
7167static inline int is_indirect_opcode(void *handler)
7168{
7169 return ((uintptr_t)handler & PPC_OPCODE_MASK) == PPC_INDIRECT;
7170}
7171
7172static inline opc_handler_t **ind_table(void *handler)
7173{
7174 return (opc_handler_t **)((uintptr_t)handler & ~PPC_OPCODE_MASK);
7175}
7176
7177/* Instruction table creation */
7178/* Opcodes tables creation */
7179static void fill_new_table(opc_handler_t **table, int len)
7180{
7181 int i;
7182
7183 for (i = 0; i < len; i++) {
7184 table[i] = &invalid_handler;
7185 }
7186}
7187
7188static int create_new_table(opc_handler_t **table, unsigned char idx)
7189{
7190 opc_handler_t **tmp;
7191
7192 tmp = g_new(opc_handler_t *, PPC_CPU_INDIRECT_OPCODES_LEN);
7193 fill_new_table(tmp, PPC_CPU_INDIRECT_OPCODES_LEN);
7194 table[idx] = (opc_handler_t *)((uintptr_t)tmp | PPC_INDIRECT);
7195
7196 return 0;
7197}
7198
7199static int insert_in_table(opc_handler_t **table, unsigned char idx,
7200 opc_handler_t *handler)
7201{
7202 if (table[idx] != &invalid_handler) {
7203 return -1;
7204 }
7205 table[idx] = handler;
7206
7207 return 0;
7208}
7209
7210static int register_direct_insn(opc_handler_t **ppc_opcodes,
7211 unsigned char idx, opc_handler_t *handler)
7212{
7213 if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
7214 printf("*** ERROR: opcode %02x already assigned in main "
7215 "opcode table\n", idx);
7468e2c8
BL
7216 return -1;
7217 }
7218
7219 return 0;
7220}
7221
7222static int register_ind_in_table(opc_handler_t **table,
7223 unsigned char idx1, unsigned char idx2,
7224 opc_handler_t *handler)
7225{
7226 if (table[idx1] == &invalid_handler) {
7227 if (create_new_table(table, idx1) < 0) {
7228 printf("*** ERROR: unable to create indirect table "
7229 "idx=%02x\n", idx1);
7230 return -1;
7231 }
7232 } else {
7233 if (!is_indirect_opcode(table[idx1])) {
7234 printf("*** ERROR: idx %02x already assigned to a direct "
7235 "opcode\n", idx1);
7468e2c8
BL
7236 return -1;
7237 }
7238 }
7239 if (handler != NULL &&
7240 insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
7241 printf("*** ERROR: opcode %02x already assigned in "
7242 "opcode table %02x\n", idx2, idx1);
7468e2c8
BL
7243 return -1;
7244 }
7245
7246 return 0;
7247}
7248
7249static int register_ind_insn(opc_handler_t **ppc_opcodes,
7250 unsigned char idx1, unsigned char idx2,
7251 opc_handler_t *handler)
7252{
7253 return register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
7254}
7255
7256static int register_dblind_insn(opc_handler_t **ppc_opcodes,
7257 unsigned char idx1, unsigned char idx2,
7258 unsigned char idx3, opc_handler_t *handler)
7259{
7260 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
7261 printf("*** ERROR: unable to join indirect table idx "
7262 "[%02x-%02x]\n", idx1, idx2);
7263 return -1;
7264 }
7265 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
7266 handler) < 0) {
7267 printf("*** ERROR: unable to insert opcode "
7268 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
7269 return -1;
7270 }
7271
7272 return 0;
7273}
7274
7275static int register_trplind_insn(opc_handler_t **ppc_opcodes,
7276 unsigned char idx1, unsigned char idx2,
7277 unsigned char idx3, unsigned char idx4,
7278 opc_handler_t *handler)
7279{
7280 opc_handler_t **table;
7281
7282 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
7283 printf("*** ERROR: unable to join indirect table idx "
7284 "[%02x-%02x]\n", idx1, idx2);
7285 return -1;
7286 }
7287 table = ind_table(ppc_opcodes[idx1]);
7288 if (register_ind_in_table(table, idx2, idx3, NULL) < 0) {
7289 printf("*** ERROR: unable to join 2nd-level indirect table idx "
7290 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
7291 return -1;
7292 }
7293 table = ind_table(table[idx2]);
7294 if (register_ind_in_table(table, idx3, idx4, handler) < 0) {
7295 printf("*** ERROR: unable to insert opcode "
7296 "[%02x-%02x-%02x-%02x]\n", idx1, idx2, idx3, idx4);
7297 return -1;
7298 }
7299 return 0;
7300}
7301static int register_insn(opc_handler_t **ppc_opcodes, opcode_t *insn)
7302{
7303 if (insn->opc2 != 0xFF) {
7304 if (insn->opc3 != 0xFF) {
7305 if (insn->opc4 != 0xFF) {
7306 if (register_trplind_insn(ppc_opcodes, insn->opc1, insn->opc2,
7307 insn->opc3, insn->opc4,
7308 &insn->handler) < 0) {
7309 return -1;
7310 }
7311 } else {
7312 if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
7313 insn->opc3, &insn->handler) < 0) {
7314 return -1;
7315 }
7316 }
7317 } else {
7318 if (register_ind_insn(ppc_opcodes, insn->opc1,
7319 insn->opc2, &insn->handler) < 0) {
7320 return -1;
7321 }
7322 }
7323 } else {
7324 if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) {
7325 return -1;
7326 }
7327 }
7328
7329 return 0;
7330}
7331
7332static int test_opcode_table(opc_handler_t **table, int len)
7333{
7334 int i, count, tmp;
7335
7336 for (i = 0, count = 0; i < len; i++) {
7337 /* Consistency fixup */
7338 if (table[i] == NULL) {
7339 table[i] = &invalid_handler;
7340 }
7341 if (table[i] != &invalid_handler) {
7342 if (is_indirect_opcode(table[i])) {
7343 tmp = test_opcode_table(ind_table(table[i]),
7344 PPC_CPU_INDIRECT_OPCODES_LEN);
7345 if (tmp == 0) {
7346 free(table[i]);
7347 table[i] = &invalid_handler;
7348 } else {
7349 count++;
7350 }
7351 } else {
7352 count++;
7353 }
7354 }
7355 }
7356
7357 return count;
7358}
7359
7360static void fix_opcode_tables(opc_handler_t **ppc_opcodes)
7361{
7362 if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) {
7363 printf("*** WARNING: no opcode defined !\n");
7364 }
7365}
7366
7367/*****************************************************************************/
7368void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
7369{
7370 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
7371 opcode_t *opc;
7372
7373 fill_new_table(cpu->opcodes, PPC_CPU_OPCODES_LEN);
7374 for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
7375 if (((opc->handler.type & pcc->insns_flags) != 0) ||
7376 ((opc->handler.type2 & pcc->insns_flags2) != 0)) {
7377 if (register_insn(cpu->opcodes, opc) < 0) {
7378 error_setg(errp, "ERROR initializing PowerPC instruction "
7379 "0x%02x 0x%02x 0x%02x", opc->opc1, opc->opc2,
7380 opc->opc3);
7381 return;
7382 }
7383 }
7384 }
7385 fix_opcode_tables(cpu->opcodes);
7386 fflush(stdout);
7387 fflush(stderr);
7388}
7389
7390void destroy_ppc_opcodes(PowerPCCPU *cpu)
7391{
7392 opc_handler_t **table, **table_2;
7393 int i, j, k;
7394
7395 for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
7396 if (cpu->opcodes[i] == &invalid_handler) {
7397 continue;
7398 }
7399 if (is_indirect_opcode(cpu->opcodes[i])) {
7400 table = ind_table(cpu->opcodes[i]);
7401 for (j = 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) {
7402 if (table[j] == &invalid_handler) {
7403 continue;
7404 }
7405 if (is_indirect_opcode(table[j])) {
7406 table_2 = ind_table(table[j]);
7407 for (k = 0; k < PPC_CPU_INDIRECT_OPCODES_LEN; k++) {
7408 if (table_2[k] != &invalid_handler &&
7409 is_indirect_opcode(table_2[k])) {
7410 g_free((opc_handler_t *)((uintptr_t)table_2[k] &
7411 ~PPC_INDIRECT));
7412 }
7413 }
7414 g_free((opc_handler_t *)((uintptr_t)table[j] &
7415 ~PPC_INDIRECT));
7416 }
7417 }
7418 g_free((opc_handler_t *)((uintptr_t)cpu->opcodes[i] &
7419 ~PPC_INDIRECT));
7420 }
7421 }
7422}
7423
7468e2c8
BL
7424int ppc_fixup_cpu(PowerPCCPU *cpu)
7425{
7426 CPUPPCState *env = &cpu->env;
7427
7428 /*
7429 * TCG doesn't (yet) emulate some groups of instructions that are
7430 * implemented on some otherwise supported CPUs (e.g. VSX and
7431 * decimal floating point instructions on POWER7). We remove
7432 * unsupported instruction groups from the cpu state's instruction
7433 * masks and hope the guest can cope. For at least the pseries
7434 * machine, the unavailability of these instructions can be
7435 * advertised to the guest via the device tree.
7436 */
7437 if ((env->insns_flags & ~PPC_TCG_INSNS)
7438 || (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
7439 warn_report("Disabling some instructions which are not "
7440 "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")",
7441 env->insns_flags & ~PPC_TCG_INSNS,
7442 env->insns_flags2 & ~PPC_TCG_INSNS2);
7443 }
7444 env->insns_flags &= PPC_TCG_INSNS;
7445 env->insns_flags2 &= PPC_TCG_INSNS2;
7446 return 0;
7447}
7448
624cb07f
RH
7449static bool decode_legacy(PowerPCCPU *cpu, DisasContext *ctx, uint32_t insn)
7450{
7451 opc_handler_t **table, *handler;
7452 uint32_t inval;
7453
7454 ctx->opcode = insn;
7455
7456 LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n",
7457 insn, opc1(insn), opc2(insn), opc3(insn), opc4(insn),
7458 ctx->le_mode ? "little" : "big");
7459
7460 table = cpu->opcodes;
7461 handler = table[opc1(insn)];
7462 if (is_indirect_opcode(handler)) {
7463 table = ind_table(handler);
7464 handler = table[opc2(insn)];
7465 if (is_indirect_opcode(handler)) {
7466 table = ind_table(handler);
7467 handler = table[opc3(insn)];
7468 if (is_indirect_opcode(handler)) {
7469 table = ind_table(handler);
7470 handler = table[opc4(insn)];
7471 }
7472 }
7473 }
7474
7475 /* Is opcode *REALLY* valid ? */
7476 if (unlikely(handler->handler == &gen_invalid)) {
7477 qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
7478 "%02x - %02x - %02x - %02x (%08x) "
7479 TARGET_FMT_lx "\n",
7480 opc1(insn), opc2(insn), opc3(insn), opc4(insn),
7481 insn, ctx->cia);
7482 return false;
7483 }
7484
7485 if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE)
7486 && Rc(insn))) {
7487 inval = handler->inval2;
7488 } else {
7489 inval = handler->inval1;
7490 }
7491
7492 if (unlikely((insn & inval) != 0)) {
7493 qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
7494 "%02x - %02x - %02x - %02x (%08x) "
7495 TARGET_FMT_lx "\n", insn & inval,
7496 opc1(insn), opc2(insn), opc3(insn), opc4(insn),
7497 insn, ctx->cia);
7498 return false;
7499 }
7500
7501 handler->handler(ctx);
7502 return true;
7503}
7504
b542683d 7505static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
79aceca5 7506{
b0c2d521 7507 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 7508 CPUPPCState *env = cs->env_ptr;
2df4fe7a 7509 uint32_t hflags = ctx->base.tb->flags;
b0c2d521 7510
b0c2d521 7511 ctx->spr_cb = env->spr_cb;
2df4fe7a 7512 ctx->pr = (hflags >> HFLAGS_PR) & 1;
d764184d 7513 ctx->mem_idx = (hflags >> HFLAGS_DMMU_IDX) & 7;
2df4fe7a
RH
7514 ctx->dr = (hflags >> HFLAGS_DR) & 1;
7515 ctx->hv = (hflags >> HFLAGS_HV) & 1;
b0c2d521
EC
7516 ctx->insns_flags = env->insns_flags;
7517 ctx->insns_flags2 = env->insns_flags2;
7518 ctx->access_type = -1;
d57d72a8 7519 ctx->need_access_type = !mmu_is_64bit(env->mmu_model);
2df4fe7a 7520 ctx->le_mode = (hflags >> HFLAGS_LE) & 1;
b0c2d521 7521 ctx->default_tcg_memop_mask = ctx->le_mode ? MO_LE : MO_BE;
0e3bf489 7522 ctx->flags = env->flags;
d9bce9d9 7523#if defined(TARGET_PPC64)
2df4fe7a 7524 ctx->sf_mode = (hflags >> HFLAGS_64) & 1;
b0c2d521 7525 ctx->has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9a64fbe4 7526#endif
e69ba2b4 7527 ctx->lazy_tlb_flush = env->mmu_model == POWERPC_MMU_32B
d55dfd44 7528 || env->mmu_model & POWERPC_MMU_64;
c5a8d8f3 7529
2df4fe7a
RH
7530 ctx->fpu_enabled = (hflags >> HFLAGS_FP) & 1;
7531 ctx->spe_enabled = (hflags >> HFLAGS_SPE) & 1;
7532 ctx->altivec_enabled = (hflags >> HFLAGS_VR) & 1;
7533 ctx->vsx_enabled = (hflags >> HFLAGS_VSX) & 1;
2df4fe7a 7534 ctx->tm_enabled = (hflags >> HFLAGS_TM) & 1;
f03de3b4 7535 ctx->gtse = (hflags >> HFLAGS_GTSE) & 1;
1db3632a 7536 ctx->hr = (hflags >> HFLAGS_HR) & 1;
f7460df2
DHB
7537 ctx->mmcr0_pmcc0 = (hflags >> HFLAGS_PMCC0) & 1;
7538 ctx->mmcr0_pmcc1 = (hflags >> HFLAGS_PMCC1) & 1;
8b3d1c49
LL
7539 ctx->mmcr0_pmcjce = (hflags >> HFLAGS_PMCJCE) & 1;
7540 ctx->pmc_other = (hflags >> HFLAGS_PMC_OTHER) & 1;
46d396bd 7541 ctx->pmu_insn_cnt = (hflags >> HFLAGS_INSN_CNT) & 1;
2df4fe7a
RH
7542
7543 ctx->singlestep_enabled = 0;
7544 if ((hflags >> HFLAGS_SE) & 1) {
7545 ctx->singlestep_enabled |= CPU_SINGLE_STEP;
9498d103 7546 ctx->base.max_insns = 1;
efe843d8 7547 }
2df4fe7a 7548 if ((hflags >> HFLAGS_BE) & 1) {
b0c2d521 7549 ctx->singlestep_enabled |= CPU_BRANCH_STEP;
efe843d8 7550 }
b0c2d521
EC
7551}
7552
7553static void ppc_tr_tb_start(DisasContextBase *db, CPUState *cs)
7554{
7555}
7556
7557static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
7558{
7559 tcg_gen_insn_start(dcbase->pc_next);
7560}
7561
99082815
RH
7562static bool is_prefix_insn(DisasContext *ctx, uint32_t insn)
7563{
7564 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
7565 return opc1(insn) == 1;
7566}
7567
b0c2d521
EC
7568static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
7569{
7570 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28876bf2 7571 PowerPCCPU *cpu = POWERPC_CPU(cs);
b0c2d521 7572 CPUPPCState *env = cs->env_ptr;
99082815 7573 target_ulong pc;
624cb07f
RH
7574 uint32_t insn;
7575 bool ok;
b0c2d521
EC
7576
7577 LOG_DISAS("----------------\n");
7578 LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
7579 ctx->base.pc_next, ctx->mem_idx, (int)msr_ir);
7580
99082815 7581 ctx->cia = pc = ctx->base.pc_next;
4e116893 7582 insn = translator_ldl_swap(env, dcbase, pc, need_byteswap(ctx));
99082815 7583 ctx->base.pc_next = pc += 4;
70560da7 7584
99082815
RH
7585 if (!is_prefix_insn(ctx, insn)) {
7586 ok = (decode_insn32(ctx, insn) ||
7587 decode_legacy(cpu, ctx, insn));
7588 } else if ((pc & 63) == 0) {
7589 /*
7590 * Power v3.1, section 1.9 Exceptions:
7591 * attempt to execute a prefixed instruction that crosses a
7592 * 64-byte address boundary (system alignment error).
7593 */
7594 gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_INSN);
7595 ok = true;
7596 } else {
4e116893
IL
7597 uint32_t insn2 = translator_ldl_swap(env, dcbase, pc,
7598 need_byteswap(ctx));
99082815
RH
7599 ctx->base.pc_next = pc += 4;
7600 ok = decode_insn64(ctx, deposit64(insn2, 32, 32, insn));
7601 }
624cb07f
RH
7602 if (!ok) {
7603 gen_invalid(ctx);
b0c2d521 7604 }
624cb07f 7605
64a0f644 7606 /* End the TB when crossing a page boundary. */
99082815 7607 if (ctx->base.is_jmp == DISAS_NEXT && !(pc & ~TARGET_PAGE_MASK)) {
64a0f644
RH
7608 ctx->base.is_jmp = DISAS_TOO_MANY;
7609 }
7610
51eb7b1d 7611 translator_loop_temp_check(&ctx->base);
b0c2d521
EC
7612}
7613
7614static void ppc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
7615{
7616 DisasContext *ctx = container_of(dcbase, DisasContext, base);
a9b5b3d0
RH
7617 DisasJumpType is_jmp = ctx->base.is_jmp;
7618 target_ulong nip = ctx->base.pc_next;
b0c2d521 7619
a9b5b3d0
RH
7620 if (is_jmp == DISAS_NORETURN) {
7621 /* We have already exited the TB. */
3d8a5b69
RH
7622 return;
7623 }
7624
a9b5b3d0 7625 /* Honor single stepping. */
9498d103
RH
7626 if (unlikely(ctx->singlestep_enabled & CPU_SINGLE_STEP)
7627 && (nip <= 0x100 || nip > 0xf00)) {
a9b5b3d0
RH
7628 switch (is_jmp) {
7629 case DISAS_TOO_MANY:
7630 case DISAS_EXIT_UPDATE:
7631 case DISAS_CHAIN_UPDATE:
7632 gen_update_nip(ctx, nip);
7633 break;
7634 case DISAS_EXIT:
7635 case DISAS_CHAIN:
7636 break;
7637 default:
7638 g_assert_not_reached();
8cbcb4fa 7639 }
13b45575 7640
9498d103
RH
7641 gen_debug_exception(ctx);
7642 return;
a9b5b3d0
RH
7643 }
7644
7645 switch (is_jmp) {
7646 case DISAS_TOO_MANY:
7647 if (use_goto_tb(ctx, nip)) {
46d396bd 7648 pmu_count_insns(ctx);
a9b5b3d0
RH
7649 tcg_gen_goto_tb(0);
7650 gen_update_nip(ctx, nip);
7651 tcg_gen_exit_tb(ctx->base.tb, 0);
7652 break;
7653 }
7654 /* fall through */
7655 case DISAS_CHAIN_UPDATE:
7656 gen_update_nip(ctx, nip);
7657 /* fall through */
7658 case DISAS_CHAIN:
46d396bd
DHB
7659 /*
7660 * tcg_gen_lookup_and_goto_ptr will exit the TB if
7661 * CF_NO_GOTO_PTR is set. Count insns now.
7662 */
7663 if (ctx->base.tb->flags & CF_NO_GOTO_PTR) {
7664 pmu_count_insns(ctx);
7665 }
7666
a9b5b3d0
RH
7667 tcg_gen_lookup_and_goto_ptr();
7668 break;
7669
7670 case DISAS_EXIT_UPDATE:
7671 gen_update_nip(ctx, nip);
7672 /* fall through */
7673 case DISAS_EXIT:
46d396bd 7674 pmu_count_insns(ctx);
07ea28b4 7675 tcg_gen_exit_tb(NULL, 0);
a9b5b3d0
RH
7676 break;
7677
7678 default:
7679 g_assert_not_reached();
9a64fbe4 7680 }
b0c2d521
EC
7681}
7682
8eb806a7
RH
7683static void ppc_tr_disas_log(const DisasContextBase *dcbase,
7684 CPUState *cs, FILE *logfile)
b0c2d521 7685{
8eb806a7
RH
7686 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
7687 target_disas(logfile, cs, dcbase->pc_first, dcbase->tb->size);
b0c2d521 7688}
0a7df5da 7689
b0c2d521
EC
7690static const TranslatorOps ppc_tr_ops = {
7691 .init_disas_context = ppc_tr_init_disas_context,
7692 .tb_start = ppc_tr_tb_start,
7693 .insn_start = ppc_tr_insn_start,
b0c2d521
EC
7694 .translate_insn = ppc_tr_translate_insn,
7695 .tb_stop = ppc_tr_tb_stop,
7696 .disas_log = ppc_tr_disas_log,
7697};
4e5e1215 7698
306c8721
RH
7699void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
7700 target_ulong pc, void *host_pc)
b0c2d521
EC
7701{
7702 DisasContext ctx;
7703
306c8721 7704 translator_loop(cs, tb, max_insns, pc, host_pc, &ppc_tr_ops, &ctx.base);
79aceca5 7705}