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