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