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