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