]> git.proxmox.com Git - qemu.git/blame - target-ppc/translate.c
qxl: create slots on post_load in vga state
[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
FB
20#include <stdarg.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <inttypes.h>
25
79aceca5 26#include "cpu.h"
79aceca5 27#include "disas.h"
57fec1fe 28#include "tcg-op.h"
ca10f867 29#include "qemu-common.h"
0cfe11ea 30#include "host-utils.h"
79aceca5 31
a7812ae4
PB
32#include "helper.h"
33#define GEN_HELPER 1
34#include "helper.h"
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 */
a7812ae4 53static TCGv_ptr cpu_env;
1d542695 54static char cpu_reg_names[10*3 + 22*4 /* GPR */
f78fb44e 55#if !defined(TARGET_PPC64)
1d542695 56 + 10*4 + 22*5 /* SPE GPRh */
f78fb44e 57#endif
a5e26afa 58 + 10*4 + 22*5 /* FPR */
47e4661c
AJ
59 + 2*(10*6 + 22*7) /* AVRh, AVRl */
60 + 8*5 /* CRF */];
f78fb44e
AJ
61static TCGv cpu_gpr[32];
62#if !defined(TARGET_PPC64)
63static TCGv cpu_gprh[32];
64#endif
a7812ae4
PB
65static TCGv_i64 cpu_fpr[32];
66static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
67static TCGv_i32 cpu_crf[8];
bd568f18 68static TCGv cpu_nip;
6527f6ea 69static TCGv cpu_msr;
cfdcd37a
AJ
70static TCGv cpu_ctr;
71static TCGv cpu_lr;
697ab892
DG
72#if defined(TARGET_PPC64)
73static TCGv cpu_cfar;
74#endif
3d7b417e 75static TCGv cpu_xer;
cf360a32 76static TCGv cpu_reserve;
a7812ae4 77static TCGv_i32 cpu_fpscr;
a7859e89 78static TCGv_i32 cpu_access_type;
f78fb44e 79
2e70f6ef
PB
80#include "gen-icount.h"
81
82void ppc_translate_init(void)
83{
f78fb44e
AJ
84 int i;
85 char* p;
2dc766da 86 size_t cpu_reg_names_size;
b2437bf2 87 static int done_init = 0;
f78fb44e 88
2e70f6ef
PB
89 if (done_init)
90 return;
f78fb44e 91
a7812ae4 92 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
a7812ae4 93
f78fb44e 94 p = cpu_reg_names;
2dc766da 95 cpu_reg_names_size = sizeof(cpu_reg_names);
47e4661c
AJ
96
97 for (i = 0; i < 8; i++) {
2dc766da 98 snprintf(p, cpu_reg_names_size, "crf%d", i);
a7812ae4
PB
99 cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
100 offsetof(CPUState, crf[i]), p);
47e4661c 101 p += 5;
2dc766da 102 cpu_reg_names_size -= 5;
47e4661c
AJ
103 }
104
f78fb44e 105 for (i = 0; i < 32; i++) {
2dc766da 106 snprintf(p, cpu_reg_names_size, "r%d", i);
a7812ae4 107 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
f78fb44e
AJ
108 offsetof(CPUState, gpr[i]), p);
109 p += (i < 10) ? 3 : 4;
2dc766da 110 cpu_reg_names_size -= (i < 10) ? 3 : 4;
f78fb44e 111#if !defined(TARGET_PPC64)
2dc766da 112 snprintf(p, cpu_reg_names_size, "r%dH", i);
a7812ae4
PB
113 cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
114 offsetof(CPUState, gprh[i]), p);
f78fb44e 115 p += (i < 10) ? 4 : 5;
2dc766da 116 cpu_reg_names_size -= (i < 10) ? 4 : 5;
f78fb44e 117#endif
1d542695 118
2dc766da 119 snprintf(p, cpu_reg_names_size, "fp%d", i);
a7812ae4
PB
120 cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
121 offsetof(CPUState, fpr[i]), p);
ec1ac72d 122 p += (i < 10) ? 4 : 5;
2dc766da 123 cpu_reg_names_size -= (i < 10) ? 4 : 5;
a5e26afa 124
2dc766da 125 snprintf(p, cpu_reg_names_size, "avr%dH", i);
e2542fe2 126#ifdef HOST_WORDS_BIGENDIAN
fe1e5c53
AJ
127 cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
128 offsetof(CPUState, avr[i].u64[0]), p);
129#else
a7812ae4 130 cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
fe1e5c53
AJ
131 offsetof(CPUState, avr[i].u64[1]), p);
132#endif
1d542695 133 p += (i < 10) ? 6 : 7;
2dc766da 134 cpu_reg_names_size -= (i < 10) ? 6 : 7;
ec1ac72d 135
2dc766da 136 snprintf(p, cpu_reg_names_size, "avr%dL", i);
e2542fe2 137#ifdef HOST_WORDS_BIGENDIAN
fe1e5c53
AJ
138 cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
139 offsetof(CPUState, avr[i].u64[1]), p);
140#else
a7812ae4 141 cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
fe1e5c53
AJ
142 offsetof(CPUState, avr[i].u64[0]), p);
143#endif
1d542695 144 p += (i < 10) ? 6 : 7;
2dc766da 145 cpu_reg_names_size -= (i < 10) ? 6 : 7;
f78fb44e 146 }
f10dc08e 147
a7812ae4 148 cpu_nip = tcg_global_mem_new(TCG_AREG0,
bd568f18
AJ
149 offsetof(CPUState, nip), "nip");
150
6527f6ea
AJ
151 cpu_msr = tcg_global_mem_new(TCG_AREG0,
152 offsetof(CPUState, msr), "msr");
153
a7812ae4 154 cpu_ctr = tcg_global_mem_new(TCG_AREG0,
cfdcd37a
AJ
155 offsetof(CPUState, ctr), "ctr");
156
a7812ae4 157 cpu_lr = tcg_global_mem_new(TCG_AREG0,
cfdcd37a
AJ
158 offsetof(CPUState, lr), "lr");
159
697ab892
DG
160#if defined(TARGET_PPC64)
161 cpu_cfar = tcg_global_mem_new(TCG_AREG0,
162 offsetof(CPUState, cfar), "cfar");
163#endif
164
a7812ae4 165 cpu_xer = tcg_global_mem_new(TCG_AREG0,
3d7b417e
AJ
166 offsetof(CPUState, xer), "xer");
167
cf360a32 168 cpu_reserve = tcg_global_mem_new(TCG_AREG0,
18b21a2f
NF
169 offsetof(CPUState, reserve_addr),
170 "reserve_addr");
cf360a32 171
a7812ae4
PB
172 cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
173 offsetof(CPUState, fpscr), "fpscr");
e1571908 174
a7859e89
AJ
175 cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
176 offsetof(CPUState, access_type), "access_type");
177
f10dc08e 178 /* register helpers */
a7812ae4 179#define GEN_HELPER 2
f10dc08e
AJ
180#include "helper.h"
181
2e70f6ef
PB
182 done_init = 1;
183}
184
79aceca5
FB
185/* internal defines */
186typedef struct DisasContext {
187 struct TranslationBlock *tb;
0fa85d43 188 target_ulong nip;
79aceca5 189 uint32_t opcode;
9a64fbe4 190 uint32_t exception;
3cc62370
FB
191 /* Routine used to access memory */
192 int mem_idx;
76db3ba4 193 int access_type;
3cc62370 194 /* Translation flags */
76db3ba4 195 int le_mode;
d9bce9d9
JM
196#if defined(TARGET_PPC64)
197 int sf_mode;
697ab892 198 int has_cfar;
9a64fbe4 199#endif
3cc62370 200 int fpu_enabled;
a9d9eb8f 201 int altivec_enabled;
0487d6a8 202 int spe_enabled;
c227f099 203 ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
ea4e754f 204 int singlestep_enabled;
79aceca5
FB
205} DisasContext;
206
c227f099 207struct opc_handler_t {
79aceca5
FB
208 /* invalid bits */
209 uint32_t inval;
9a64fbe4 210 /* instruction type */
0487d6a8 211 uint64_t type;
a5858d7a
AG
212 /* extended instruction type */
213 uint64_t type2;
79aceca5
FB
214 /* handler */
215 void (*handler)(DisasContext *ctx);
a750fc0b 216#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
b55266b5 217 const char *oname;
a750fc0b
JM
218#endif
219#if defined(DO_PPC_STATISTICS)
76a66253
JM
220 uint64_t count;
221#endif
3fc6c082 222};
79aceca5 223
636aa200 224static inline void gen_reset_fpstatus(void)
7c58044c 225{
a44d2ce1 226 gen_helper_reset_fpstatus();
7c58044c
JM
227}
228
636aa200 229static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
7c58044c 230{
0f2f39c2 231 TCGv_i32 t0 = tcg_temp_new_i32();
af12906f 232
7c58044c
JM
233 if (set_fprf != 0) {
234 /* This case might be optimized later */
0f2f39c2 235 tcg_gen_movi_i32(t0, 1);
af12906f 236 gen_helper_compute_fprf(t0, arg, t0);
a7812ae4 237 if (unlikely(set_rc)) {
0f2f39c2 238 tcg_gen_mov_i32(cpu_crf[1], t0);
a7812ae4 239 }
af12906f 240 gen_helper_float_check_status();
7c58044c
JM
241 } else if (unlikely(set_rc)) {
242 /* We always need to compute fpcc */
0f2f39c2 243 tcg_gen_movi_i32(t0, 0);
af12906f 244 gen_helper_compute_fprf(t0, arg, t0);
0f2f39c2 245 tcg_gen_mov_i32(cpu_crf[1], t0);
7c58044c 246 }
af12906f 247
0f2f39c2 248 tcg_temp_free_i32(t0);
7c58044c
JM
249}
250
636aa200 251static inline void gen_set_access_type(DisasContext *ctx, int access_type)
a7859e89 252{
76db3ba4
AJ
253 if (ctx->access_type != access_type) {
254 tcg_gen_movi_i32(cpu_access_type, access_type);
255 ctx->access_type = access_type;
256 }
a7859e89
AJ
257}
258
636aa200 259static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
d9bce9d9
JM
260{
261#if defined(TARGET_PPC64)
262 if (ctx->sf_mode)
bd568f18 263 tcg_gen_movi_tl(cpu_nip, nip);
d9bce9d9
JM
264 else
265#endif
bd568f18 266 tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
d9bce9d9
JM
267}
268
636aa200 269static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
e06fcd75
AJ
270{
271 TCGv_i32 t0, t1;
272 if (ctx->exception == POWERPC_EXCP_NONE) {
273 gen_update_nip(ctx, ctx->nip);
274 }
275 t0 = tcg_const_i32(excp);
276 t1 = tcg_const_i32(error);
277 gen_helper_raise_exception_err(t0, t1);
278 tcg_temp_free_i32(t0);
279 tcg_temp_free_i32(t1);
280 ctx->exception = (excp);
281}
e1833e1f 282
636aa200 283static inline void gen_exception(DisasContext *ctx, uint32_t excp)
e06fcd75
AJ
284{
285 TCGv_i32 t0;
286 if (ctx->exception == POWERPC_EXCP_NONE) {
287 gen_update_nip(ctx, ctx->nip);
288 }
289 t0 = tcg_const_i32(excp);
290 gen_helper_raise_exception(t0);
291 tcg_temp_free_i32(t0);
292 ctx->exception = (excp);
293}
e1833e1f 294
636aa200 295static inline void gen_debug_exception(DisasContext *ctx)
e06fcd75
AJ
296{
297 TCGv_i32 t0;
5518f3a6
BS
298
299 if (ctx->exception != POWERPC_EXCP_BRANCH)
300 gen_update_nip(ctx, ctx->nip);
e06fcd75
AJ
301 t0 = tcg_const_i32(EXCP_DEBUG);
302 gen_helper_raise_exception(t0);
303 tcg_temp_free_i32(t0);
304}
9a64fbe4 305
636aa200 306static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
e06fcd75
AJ
307{
308 gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | error);
309}
a9d9eb8f 310
f24e5695 311/* Stop translation */
636aa200 312static inline void gen_stop_exception(DisasContext *ctx)
3fc6c082 313{
d9bce9d9 314 gen_update_nip(ctx, ctx->nip);
e1833e1f 315 ctx->exception = POWERPC_EXCP_STOP;
3fc6c082
FB
316}
317
f24e5695 318/* No need to update nip here, as execution flow will change */
636aa200 319static inline void gen_sync_exception(DisasContext *ctx)
2be0071f 320{
e1833e1f 321 ctx->exception = POWERPC_EXCP_SYNC;
2be0071f
FB
322}
323
79aceca5 324#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
a5858d7a
AG
325GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
326
327#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2) \
328GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
79aceca5 329
c7697e1f 330#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
a5858d7a
AG
331GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
332
333#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2) \
334GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
c7697e1f 335
c227f099 336typedef struct opcode_t {
79aceca5 337 unsigned char opc1, opc2, opc3;
1235fc06 338#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
18fba28c
FB
339 unsigned char pad[5];
340#else
341 unsigned char pad[1];
342#endif
c227f099 343 opc_handler_t handler;
b55266b5 344 const char *oname;
c227f099 345} opcode_t;
79aceca5 346
a750fc0b 347/*****************************************************************************/
79aceca5
FB
348/*** Instruction decoding ***/
349#define EXTRACT_HELPER(name, shift, nb) \
636aa200 350static inline uint32_t name(uint32_t opcode) \
79aceca5
FB
351{ \
352 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
353}
354
355#define EXTRACT_SHELPER(name, shift, nb) \
636aa200 356static inline int32_t name(uint32_t opcode) \
79aceca5 357{ \
18fba28c 358 return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
79aceca5
FB
359}
360
361/* Opcode part 1 */
362EXTRACT_HELPER(opc1, 26, 6);
363/* Opcode part 2 */
364EXTRACT_HELPER(opc2, 1, 5);
365/* Opcode part 3 */
366EXTRACT_HELPER(opc3, 6, 5);
367/* Update Cr0 flags */
368EXTRACT_HELPER(Rc, 0, 1);
369/* Destination */
370EXTRACT_HELPER(rD, 21, 5);
371/* Source */
372EXTRACT_HELPER(rS, 21, 5);
373/* First operand */
374EXTRACT_HELPER(rA, 16, 5);
375/* Second operand */
376EXTRACT_HELPER(rB, 11, 5);
377/* Third operand */
378EXTRACT_HELPER(rC, 6, 5);
379/*** Get CRn ***/
380EXTRACT_HELPER(crfD, 23, 3);
381EXTRACT_HELPER(crfS, 18, 3);
382EXTRACT_HELPER(crbD, 21, 5);
383EXTRACT_HELPER(crbA, 16, 5);
384EXTRACT_HELPER(crbB, 11, 5);
385/* SPR / TBL */
3fc6c082 386EXTRACT_HELPER(_SPR, 11, 10);
636aa200 387static inline uint32_t SPR(uint32_t opcode)
3fc6c082
FB
388{
389 uint32_t sprn = _SPR(opcode);
390
391 return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
392}
79aceca5
FB
393/*** Get constants ***/
394EXTRACT_HELPER(IMM, 12, 8);
395/* 16 bits signed immediate value */
396EXTRACT_SHELPER(SIMM, 0, 16);
397/* 16 bits unsigned immediate value */
398EXTRACT_HELPER(UIMM, 0, 16);
21d21583
AJ
399/* 5 bits signed immediate value */
400EXTRACT_HELPER(SIMM5, 16, 5);
27a4edb3
AJ
401/* 5 bits signed immediate value */
402EXTRACT_HELPER(UIMM5, 16, 5);
79aceca5
FB
403/* Bit count */
404EXTRACT_HELPER(NB, 11, 5);
405/* Shift count */
406EXTRACT_HELPER(SH, 11, 5);
cd633b10
AJ
407/* Vector shift count */
408EXTRACT_HELPER(VSH, 6, 4);
79aceca5
FB
409/* Mask start */
410EXTRACT_HELPER(MB, 6, 5);
411/* Mask end */
412EXTRACT_HELPER(ME, 1, 5);
fb0eaffc
FB
413/* Trap operand */
414EXTRACT_HELPER(TO, 21, 5);
79aceca5
FB
415
416EXTRACT_HELPER(CRM, 12, 8);
417EXTRACT_HELPER(FM, 17, 8);
418EXTRACT_HELPER(SR, 16, 4);
e4bb997e 419EXTRACT_HELPER(FPIMM, 12, 4);
fb0eaffc 420
79aceca5
FB
421/*** Jump target decoding ***/
422/* Displacement */
423EXTRACT_SHELPER(d, 0, 16);
424/* Immediate address */
636aa200 425static inline target_ulong LI(uint32_t opcode)
79aceca5
FB
426{
427 return (opcode >> 0) & 0x03FFFFFC;
428}
429
636aa200 430static inline uint32_t BD(uint32_t opcode)
79aceca5
FB
431{
432 return (opcode >> 0) & 0xFFFC;
433}
434
435EXTRACT_HELPER(BO, 21, 5);
436EXTRACT_HELPER(BI, 16, 5);
437/* Absolute/relative address */
438EXTRACT_HELPER(AA, 1, 1);
439/* Link */
440EXTRACT_HELPER(LK, 0, 1);
441
442/* Create a mask between <start> and <end> bits */
636aa200 443static inline target_ulong MASK(uint32_t start, uint32_t end)
79aceca5 444{
76a66253 445 target_ulong ret;
79aceca5 446
76a66253
JM
447#if defined(TARGET_PPC64)
448 if (likely(start == 0)) {
6f2d8978 449 ret = UINT64_MAX << (63 - end);
76a66253 450 } else if (likely(end == 63)) {
6f2d8978 451 ret = UINT64_MAX >> start;
76a66253
JM
452 }
453#else
454 if (likely(start == 0)) {
6f2d8978 455 ret = UINT32_MAX << (31 - end);
76a66253 456 } else if (likely(end == 31)) {
6f2d8978 457 ret = UINT32_MAX >> start;
76a66253
JM
458 }
459#endif
460 else {
461 ret = (((target_ulong)(-1ULL)) >> (start)) ^
462 (((target_ulong)(-1ULL) >> (end)) >> 1);
463 if (unlikely(start > end))
464 return ~ret;
465 }
79aceca5
FB
466
467 return ret;
468}
469
a750fc0b 470/*****************************************************************************/
a750fc0b 471/* PowerPC instructions table */
933dc6eb 472
76a66253 473#if defined(DO_PPC_STATISTICS)
a5858d7a 474#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 475{ \
79aceca5
FB
476 .opc1 = op1, \
477 .opc2 = op2, \
478 .opc3 = op3, \
18fba28c 479 .pad = { 0, }, \
79aceca5
FB
480 .handler = { \
481 .inval = invl, \
9a64fbe4 482 .type = _typ, \
a5858d7a 483 .type2 = _typ2, \
79aceca5 484 .handler = &gen_##name, \
76a66253 485 .oname = stringify(name), \
79aceca5 486 }, \
3fc6c082 487 .oname = stringify(name), \
79aceca5 488}
a5858d7a 489#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 490{ \
c7697e1f
JM
491 .opc1 = op1, \
492 .opc2 = op2, \
493 .opc3 = op3, \
494 .pad = { 0, }, \
495 .handler = { \
496 .inval = invl, \
497 .type = _typ, \
a5858d7a 498 .type2 = _typ2, \
c7697e1f
JM
499 .handler = &gen_##name, \
500 .oname = onam, \
501 }, \
502 .oname = onam, \
503}
76a66253 504#else
a5858d7a 505#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99 506{ \
c7697e1f
JM
507 .opc1 = op1, \
508 .opc2 = op2, \
509 .opc3 = op3, \
510 .pad = { 0, }, \
511 .handler = { \
512 .inval = invl, \
513 .type = _typ, \
a5858d7a 514 .type2 = _typ2, \
c7697e1f 515 .handler = &gen_##name, \
5c55ff99
BS
516 }, \
517 .oname = stringify(name), \
518}
a5858d7a 519#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
5c55ff99
BS
520{ \
521 .opc1 = op1, \
522 .opc2 = op2, \
523 .opc3 = op3, \
524 .pad = { 0, }, \
525 .handler = { \
526 .inval = invl, \
527 .type = _typ, \
a5858d7a 528 .type2 = _typ2, \
5c55ff99
BS
529 .handler = &gen_##name, \
530 }, \
531 .oname = onam, \
532}
533#endif
2e610050 534
5c55ff99 535/* SPR load/store helpers */
636aa200 536static inline void gen_load_spr(TCGv t, int reg)
5c55ff99
BS
537{
538 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
539}
2e610050 540
636aa200 541static inline void gen_store_spr(int reg, TCGv t)
5c55ff99
BS
542{
543 tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
544}
2e610050 545
54623277 546/* Invalid instruction */
99e300ef 547static void gen_invalid(DisasContext *ctx)
9a64fbe4 548{
e06fcd75 549 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
9a64fbe4
FB
550}
551
c227f099 552static opc_handler_t invalid_handler = {
79aceca5 553 .inval = 0xFFFFFFFF,
9a64fbe4 554 .type = PPC_NONE,
a5858d7a 555 .type2 = PPC_NONE,
79aceca5
FB
556 .handler = gen_invalid,
557};
558
e1571908
AJ
559/*** Integer comparison ***/
560
636aa200 561static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
e1571908
AJ
562{
563 int l1, l2, l3;
564
269f3e95
AJ
565 tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
566 tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
e1571908
AJ
567 tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);
568
569 l1 = gen_new_label();
570 l2 = gen_new_label();
571 l3 = gen_new_label();
572 if (s) {
ea363694
AJ
573 tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
574 tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
e1571908 575 } else {
ea363694
AJ
576 tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
577 tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
e1571908
AJ
578 }
579 tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
580 tcg_gen_br(l3);
581 gen_set_label(l1);
582 tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
583 tcg_gen_br(l3);
584 gen_set_label(l2);
585 tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
586 gen_set_label(l3);
587}
588
636aa200 589static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 590{
ea363694
AJ
591 TCGv t0 = tcg_const_local_tl(arg1);
592 gen_op_cmp(arg0, t0, s, crf);
593 tcg_temp_free(t0);
e1571908
AJ
594}
595
596#if defined(TARGET_PPC64)
636aa200 597static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
e1571908 598{
ea363694 599 TCGv t0, t1;
a7812ae4
PB
600 t0 = tcg_temp_local_new();
601 t1 = tcg_temp_local_new();
e1571908 602 if (s) {
ea363694
AJ
603 tcg_gen_ext32s_tl(t0, arg0);
604 tcg_gen_ext32s_tl(t1, arg1);
e1571908 605 } else {
ea363694
AJ
606 tcg_gen_ext32u_tl(t0, arg0);
607 tcg_gen_ext32u_tl(t1, arg1);
e1571908 608 }
ea363694
AJ
609 gen_op_cmp(t0, t1, s, crf);
610 tcg_temp_free(t1);
611 tcg_temp_free(t0);
e1571908
AJ
612}
613
636aa200 614static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 615{
ea363694
AJ
616 TCGv t0 = tcg_const_local_tl(arg1);
617 gen_op_cmp32(arg0, t0, s, crf);
618 tcg_temp_free(t0);
e1571908
AJ
619}
620#endif
621
636aa200 622static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
e1571908
AJ
623{
624#if defined(TARGET_PPC64)
625 if (!(ctx->sf_mode))
626 gen_op_cmpi32(reg, 0, 1, 0);
627 else
628#endif
629 gen_op_cmpi(reg, 0, 1, 0);
630}
631
632/* cmp */
99e300ef 633static void gen_cmp(DisasContext *ctx)
e1571908
AJ
634{
635#if defined(TARGET_PPC64)
636 if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
637 gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
638 1, crfD(ctx->opcode));
639 else
640#endif
641 gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
642 1, crfD(ctx->opcode));
643}
644
645/* cmpi */
99e300ef 646static void gen_cmpi(DisasContext *ctx)
e1571908
AJ
647{
648#if defined(TARGET_PPC64)
649 if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
650 gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
651 1, crfD(ctx->opcode));
652 else
653#endif
654 gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
655 1, crfD(ctx->opcode));
656}
657
658/* cmpl */
99e300ef 659static void gen_cmpl(DisasContext *ctx)
e1571908
AJ
660{
661#if defined(TARGET_PPC64)
662 if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
663 gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
664 0, crfD(ctx->opcode));
665 else
666#endif
667 gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
668 0, crfD(ctx->opcode));
669}
670
671/* cmpli */
99e300ef 672static void gen_cmpli(DisasContext *ctx)
e1571908
AJ
673{
674#if defined(TARGET_PPC64)
675 if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
676 gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
677 0, crfD(ctx->opcode));
678 else
679#endif
680 gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
681 0, crfD(ctx->opcode));
682}
683
684/* isel (PowerPC 2.03 specification) */
99e300ef 685static void gen_isel(DisasContext *ctx)
e1571908
AJ
686{
687 int l1, l2;
688 uint32_t bi = rC(ctx->opcode);
689 uint32_t mask;
a7812ae4 690 TCGv_i32 t0;
e1571908
AJ
691
692 l1 = gen_new_label();
693 l2 = gen_new_label();
694
695 mask = 1 << (3 - (bi & 0x03));
a7812ae4 696 t0 = tcg_temp_new_i32();
fea0c503
AJ
697 tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
698 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
e1571908
AJ
699 if (rA(ctx->opcode) == 0)
700 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
701 else
702 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
703 tcg_gen_br(l2);
704 gen_set_label(l1);
705 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
706 gen_set_label(l2);
a7812ae4 707 tcg_temp_free_i32(t0);
e1571908
AJ
708}
709
79aceca5 710/*** Integer arithmetic ***/
79aceca5 711
636aa200
BS
712static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
713 TCGv arg1, TCGv arg2, int sub)
74637406
AJ
714{
715 int l1;
716 TCGv t0;
79aceca5 717
74637406
AJ
718 l1 = gen_new_label();
719 /* Start with XER OV disabled, the most likely case */
720 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
a7812ae4 721 t0 = tcg_temp_local_new();
74637406
AJ
722 tcg_gen_xor_tl(t0, arg0, arg1);
723#if defined(TARGET_PPC64)
724 if (!ctx->sf_mode)
725 tcg_gen_ext32s_tl(t0, t0);
726#endif
727 if (sub)
728 tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
729 else
730 tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
731 tcg_gen_xor_tl(t0, arg1, arg2);
732#if defined(TARGET_PPC64)
733 if (!ctx->sf_mode)
734 tcg_gen_ext32s_tl(t0, t0);
735#endif
736 if (sub)
737 tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
738 else
739 tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
740 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
741 gen_set_label(l1);
742 tcg_temp_free(t0);
79aceca5
FB
743}
744
636aa200
BS
745static inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1,
746 TCGv arg2, int sub)
74637406
AJ
747{
748 int l1 = gen_new_label();
d9bce9d9
JM
749
750#if defined(TARGET_PPC64)
74637406
AJ
751 if (!(ctx->sf_mode)) {
752 TCGv t0, t1;
a7812ae4
PB
753 t0 = tcg_temp_new();
754 t1 = tcg_temp_new();
d9bce9d9 755
74637406
AJ
756 tcg_gen_ext32u_tl(t0, arg1);
757 tcg_gen_ext32u_tl(t1, arg2);
758 if (sub) {
759 tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
bdc4e053 760 } else {
74637406
AJ
761 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
762 }
a9730017
AJ
763 tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
764 gen_set_label(l1);
765 tcg_temp_free(t0);
766 tcg_temp_free(t1);
74637406
AJ
767 } else
768#endif
a9730017
AJ
769 {
770 if (sub) {
771 tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
772 } else {
773 tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
774 }
775 tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
776 gen_set_label(l1);
74637406 777 }
d9bce9d9
JM
778}
779
74637406 780/* Common add function */
636aa200
BS
781static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
782 TCGv arg2, int add_ca, int compute_ca,
783 int compute_ov)
74637406
AJ
784{
785 TCGv t0, t1;
d9bce9d9 786
74637406 787 if ((!compute_ca && !compute_ov) ||
a7812ae4 788 (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2))) {
74637406
AJ
789 t0 = ret;
790 } else {
a7812ae4 791 t0 = tcg_temp_local_new();
74637406 792 }
79aceca5 793
74637406 794 if (add_ca) {
a7812ae4 795 t1 = tcg_temp_local_new();
74637406
AJ
796 tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
797 tcg_gen_shri_tl(t1, t1, XER_CA);
d2e9fd8f 798 } else {
799 TCGV_UNUSED(t1);
74637406 800 }
79aceca5 801
74637406
AJ
802 if (compute_ca && compute_ov) {
803 /* Start with XER CA and OV disabled, the most likely case */
804 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
805 } else if (compute_ca) {
806 /* Start with XER CA disabled, the most likely case */
807 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
808 } else if (compute_ov) {
809 /* Start with XER OV disabled, the most likely case */
810 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
811 }
79aceca5 812
74637406
AJ
813 tcg_gen_add_tl(t0, arg1, arg2);
814
815 if (compute_ca) {
816 gen_op_arith_compute_ca(ctx, t0, arg1, 0);
817 }
818 if (add_ca) {
819 tcg_gen_add_tl(t0, t0, t1);
820 gen_op_arith_compute_ca(ctx, t0, t1, 0);
821 tcg_temp_free(t1);
822 }
823 if (compute_ov) {
824 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
825 }
826
827 if (unlikely(Rc(ctx->opcode) != 0))
828 gen_set_Rc0(ctx, t0);
829
a7812ae4 830 if (!TCGV_EQUAL(t0, ret)) {
74637406
AJ
831 tcg_gen_mov_tl(ret, t0);
832 tcg_temp_free(t0);
833 }
39dd32ee 834}
74637406
AJ
835/* Add functions with two operands */
836#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
99e300ef 837static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
838{ \
839 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
840 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
841 add_ca, compute_ca, compute_ov); \
842}
843/* Add functions with one operand and one immediate */
844#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
845 add_ca, compute_ca, compute_ov) \
99e300ef 846static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
847{ \
848 TCGv t0 = tcg_const_local_tl(const_val); \
849 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
850 cpu_gpr[rA(ctx->opcode)], t0, \
851 add_ca, compute_ca, compute_ov); \
852 tcg_temp_free(t0); \
853}
854
855/* add add. addo addo. */
856GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
857GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
858/* addc addc. addco addco. */
859GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
860GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
861/* adde adde. addeo addeo. */
862GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
863GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
864/* addme addme. addmeo addmeo. */
865GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
866GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
867/* addze addze. addzeo addzeo.*/
868GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
869GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
870/* addi */
99e300ef 871static void gen_addi(DisasContext *ctx)
d9bce9d9 872{
74637406
AJ
873 target_long simm = SIMM(ctx->opcode);
874
875 if (rA(ctx->opcode) == 0) {
876 /* li case */
877 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
878 } else {
879 tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
880 }
d9bce9d9 881}
74637406 882/* addic addic.*/
636aa200
BS
883static inline void gen_op_addic(DisasContext *ctx, TCGv ret, TCGv arg1,
884 int compute_Rc0)
d9bce9d9 885{
74637406
AJ
886 target_long simm = SIMM(ctx->opcode);
887
888 /* Start with XER CA and OV disabled, the most likely case */
889 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
890
891 if (likely(simm != 0)) {
a7812ae4 892 TCGv t0 = tcg_temp_local_new();
74637406
AJ
893 tcg_gen_addi_tl(t0, arg1, simm);
894 gen_op_arith_compute_ca(ctx, t0, arg1, 0);
895 tcg_gen_mov_tl(ret, t0);
896 tcg_temp_free(t0);
897 } else {
898 tcg_gen_mov_tl(ret, arg1);
899 }
900 if (compute_Rc0) {
901 gen_set_Rc0(ctx, ret);
902 }
d9bce9d9 903}
99e300ef
BS
904
905static void gen_addic(DisasContext *ctx)
d9bce9d9 906{
74637406 907 gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
d9bce9d9 908}
e8eaa2c0
BS
909
910static void gen_addic_(DisasContext *ctx)
d9bce9d9 911{
74637406 912 gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
d9bce9d9 913}
99e300ef 914
54623277 915/* addis */
99e300ef 916static void gen_addis(DisasContext *ctx)
d9bce9d9 917{
74637406
AJ
918 target_long simm = SIMM(ctx->opcode);
919
920 if (rA(ctx->opcode) == 0) {
921 /* lis case */
922 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
923 } else {
924 tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
925 }
d9bce9d9 926}
74637406 927
636aa200
BS
928static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
929 TCGv arg2, int sign, int compute_ov)
d9bce9d9 930{
2ef1b120
AJ
931 int l1 = gen_new_label();
932 int l2 = gen_new_label();
a7812ae4
PB
933 TCGv_i32 t0 = tcg_temp_local_new_i32();
934 TCGv_i32 t1 = tcg_temp_local_new_i32();
74637406 935
2ef1b120
AJ
936 tcg_gen_trunc_tl_i32(t0, arg1);
937 tcg_gen_trunc_tl_i32(t1, arg2);
938 tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
74637406 939 if (sign) {
2ef1b120
AJ
940 int l3 = gen_new_label();
941 tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
942 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
74637406 943 gen_set_label(l3);
2ef1b120 944 tcg_gen_div_i32(t0, t0, t1);
74637406 945 } else {
2ef1b120 946 tcg_gen_divu_i32(t0, t0, t1);
74637406
AJ
947 }
948 if (compute_ov) {
949 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
950 }
951 tcg_gen_br(l2);
952 gen_set_label(l1);
953 if (sign) {
2ef1b120 954 tcg_gen_sari_i32(t0, t0, 31);
74637406
AJ
955 } else {
956 tcg_gen_movi_i32(t0, 0);
957 }
958 if (compute_ov) {
959 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
960 }
961 gen_set_label(l2);
2ef1b120 962 tcg_gen_extu_i32_tl(ret, t0);
a7812ae4
PB
963 tcg_temp_free_i32(t0);
964 tcg_temp_free_i32(t1);
74637406
AJ
965 if (unlikely(Rc(ctx->opcode) != 0))
966 gen_set_Rc0(ctx, ret);
d9bce9d9 967}
74637406
AJ
968/* Div functions */
969#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
99e300ef 970static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
971{ \
972 gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)], \
973 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
974 sign, compute_ov); \
975}
976/* divwu divwu. divwuo divwuo. */
977GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
978GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
979/* divw divw. divwo divwo. */
980GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
981GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
d9bce9d9 982#if defined(TARGET_PPC64)
636aa200
BS
983static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
984 TCGv arg2, int sign, int compute_ov)
d9bce9d9 985{
2ef1b120
AJ
986 int l1 = gen_new_label();
987 int l2 = gen_new_label();
74637406
AJ
988
989 tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
990 if (sign) {
2ef1b120 991 int l3 = gen_new_label();
74637406
AJ
992 tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
993 tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
994 gen_set_label(l3);
74637406
AJ
995 tcg_gen_div_i64(ret, arg1, arg2);
996 } else {
997 tcg_gen_divu_i64(ret, arg1, arg2);
998 }
999 if (compute_ov) {
1000 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1001 }
1002 tcg_gen_br(l2);
1003 gen_set_label(l1);
1004 if (sign) {
1005 tcg_gen_sari_i64(ret, arg1, 63);
1006 } else {
1007 tcg_gen_movi_i64(ret, 0);
1008 }
1009 if (compute_ov) {
1010 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1011 }
1012 gen_set_label(l2);
1013 if (unlikely(Rc(ctx->opcode) != 0))
1014 gen_set_Rc0(ctx, ret);
d9bce9d9 1015}
74637406 1016#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
99e300ef 1017static void glue(gen_, name)(DisasContext *ctx) \
74637406 1018{ \
2ef1b120
AJ
1019 gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)], \
1020 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1021 sign, compute_ov); \
74637406
AJ
1022}
1023/* divwu divwu. divwuo divwuo. */
1024GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1025GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1026/* divw divw. divwo divwo. */
1027GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1028GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
d9bce9d9 1029#endif
74637406
AJ
1030
1031/* mulhw mulhw. */
99e300ef 1032static void gen_mulhw(DisasContext *ctx)
d9bce9d9 1033{
a7812ae4 1034 TCGv_i64 t0, t1;
74637406 1035
a7812ae4
PB
1036 t0 = tcg_temp_new_i64();
1037 t1 = tcg_temp_new_i64();
74637406
AJ
1038#if defined(TARGET_PPC64)
1039 tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1040 tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1041 tcg_gen_mul_i64(t0, t0, t1);
1042 tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1043#else
1044 tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1045 tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1046 tcg_gen_mul_i64(t0, t0, t1);
1047 tcg_gen_shri_i64(t0, t0, 32);
1048 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1049#endif
a7812ae4
PB
1050 tcg_temp_free_i64(t0);
1051 tcg_temp_free_i64(t1);
74637406
AJ
1052 if (unlikely(Rc(ctx->opcode) != 0))
1053 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1054}
99e300ef 1055
54623277 1056/* mulhwu mulhwu. */
99e300ef 1057static void gen_mulhwu(DisasContext *ctx)
d9bce9d9 1058{
a7812ae4 1059 TCGv_i64 t0, t1;
74637406 1060
a7812ae4
PB
1061 t0 = tcg_temp_new_i64();
1062 t1 = tcg_temp_new_i64();
d9bce9d9 1063#if defined(TARGET_PPC64)
74637406
AJ
1064 tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1065 tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1066 tcg_gen_mul_i64(t0, t0, t1);
1067 tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1068#else
1069 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1070 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1071 tcg_gen_mul_i64(t0, t0, t1);
1072 tcg_gen_shri_i64(t0, t0, 32);
1073 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1074#endif
a7812ae4
PB
1075 tcg_temp_free_i64(t0);
1076 tcg_temp_free_i64(t1);
74637406
AJ
1077 if (unlikely(Rc(ctx->opcode) != 0))
1078 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1079}
99e300ef 1080
54623277 1081/* mullw mullw. */
99e300ef 1082static void gen_mullw(DisasContext *ctx)
d9bce9d9 1083{
74637406
AJ
1084 tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1085 cpu_gpr[rB(ctx->opcode)]);
1e4c090f 1086 tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
74637406
AJ
1087 if (unlikely(Rc(ctx->opcode) != 0))
1088 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1089}
99e300ef 1090
54623277 1091/* mullwo mullwo. */
99e300ef 1092static void gen_mullwo(DisasContext *ctx)
d9bce9d9 1093{
74637406 1094 int l1;
a7812ae4 1095 TCGv_i64 t0, t1;
74637406 1096
a7812ae4
PB
1097 t0 = tcg_temp_new_i64();
1098 t1 = tcg_temp_new_i64();
74637406
AJ
1099 l1 = gen_new_label();
1100 /* Start with XER OV disabled, the most likely case */
1101 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1102#if defined(TARGET_PPC64)
1103 tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1104 tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1105#else
1106 tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1107 tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
d9bce9d9 1108#endif
74637406
AJ
1109 tcg_gen_mul_i64(t0, t0, t1);
1110#if defined(TARGET_PPC64)
1111 tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
1112 tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
1113#else
1114 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1115 tcg_gen_ext32s_i64(t1, t0);
1116 tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
1117#endif
1118 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1119 gen_set_label(l1);
a7812ae4
PB
1120 tcg_temp_free_i64(t0);
1121 tcg_temp_free_i64(t1);
74637406
AJ
1122 if (unlikely(Rc(ctx->opcode) != 0))
1123 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1124}
99e300ef 1125
54623277 1126/* mulli */
99e300ef 1127static void gen_mulli(DisasContext *ctx)
d9bce9d9 1128{
74637406
AJ
1129 tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1130 SIMM(ctx->opcode));
d9bce9d9
JM
1131}
1132#if defined(TARGET_PPC64)
74637406 1133#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
99e300ef 1134static void glue(gen_, name)(DisasContext *ctx) \
74637406 1135{ \
a7812ae4 1136 gen_helper_##name (cpu_gpr[rD(ctx->opcode)], \
74637406
AJ
1137 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
1138 if (unlikely(Rc(ctx->opcode) != 0)) \
1139 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); \
d9bce9d9 1140}
74637406
AJ
1141/* mulhd mulhd. */
1142GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
1143/* mulhdu mulhdu. */
1144GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
99e300ef 1145
54623277 1146/* mulld mulld. */
99e300ef 1147static void gen_mulld(DisasContext *ctx)
d9bce9d9 1148{
74637406
AJ
1149 tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1150 cpu_gpr[rB(ctx->opcode)]);
1151 if (unlikely(Rc(ctx->opcode) != 0))
1152 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1153}
74637406
AJ
1154/* mulldo mulldo. */
1155GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
d9bce9d9 1156#endif
74637406
AJ
1157
1158/* neg neg. nego nego. */
636aa200
BS
1159static inline void gen_op_arith_neg(DisasContext *ctx, TCGv ret, TCGv arg1,
1160 int ov_check)
d9bce9d9 1161{
ec6469a3
AJ
1162 int l1 = gen_new_label();
1163 int l2 = gen_new_label();
a7812ae4 1164 TCGv t0 = tcg_temp_local_new();
d9bce9d9 1165#if defined(TARGET_PPC64)
74637406 1166 if (ctx->sf_mode) {
741a7444 1167 tcg_gen_mov_tl(t0, arg1);
ec6469a3
AJ
1168 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
1169 } else
1170#endif
1171 {
1172 tcg_gen_ext32s_tl(t0, arg1);
74637406
AJ
1173 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
1174 }
74637406
AJ
1175 tcg_gen_neg_tl(ret, arg1);
1176 if (ov_check) {
1177 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1178 }
1179 tcg_gen_br(l2);
1180 gen_set_label(l1);
ec6469a3 1181 tcg_gen_mov_tl(ret, t0);
74637406
AJ
1182 if (ov_check) {
1183 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1184 }
1185 gen_set_label(l2);
ec6469a3 1186 tcg_temp_free(t0);
74637406
AJ
1187 if (unlikely(Rc(ctx->opcode) != 0))
1188 gen_set_Rc0(ctx, ret);
1189}
99e300ef
BS
1190
1191static void gen_neg(DisasContext *ctx)
d9bce9d9 1192{
ec6469a3 1193 gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
d9bce9d9 1194}
99e300ef
BS
1195
1196static void gen_nego(DisasContext *ctx)
79aceca5 1197{
ec6469a3 1198 gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
79aceca5 1199}
74637406
AJ
1200
1201/* Common subf function */
636aa200
BS
1202static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
1203 TCGv arg2, int add_ca, int compute_ca,
1204 int compute_ov)
79aceca5 1205{
74637406 1206 TCGv t0, t1;
76a66253 1207
74637406 1208 if ((!compute_ca && !compute_ov) ||
a7812ae4 1209 (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2))) {
74637406 1210 t0 = ret;
e864cabd 1211 } else {
a7812ae4 1212 t0 = tcg_temp_local_new();
d9bce9d9 1213 }
76a66253 1214
74637406 1215 if (add_ca) {
a7812ae4 1216 t1 = tcg_temp_local_new();
74637406
AJ
1217 tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
1218 tcg_gen_shri_tl(t1, t1, XER_CA);
d2e9fd8f 1219 } else {
1220 TCGV_UNUSED(t1);
d9bce9d9 1221 }
79aceca5 1222
74637406
AJ
1223 if (compute_ca && compute_ov) {
1224 /* Start with XER CA and OV disabled, the most likely case */
1225 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
1226 } else if (compute_ca) {
1227 /* Start with XER CA disabled, the most likely case */
1228 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1229 } else if (compute_ov) {
1230 /* Start with XER OV disabled, the most likely case */
1231 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1232 }
1233
1234 if (add_ca) {
1235 tcg_gen_not_tl(t0, arg1);
1236 tcg_gen_add_tl(t0, t0, arg2);
1237 gen_op_arith_compute_ca(ctx, t0, arg2, 0);
1238 tcg_gen_add_tl(t0, t0, t1);
1239 gen_op_arith_compute_ca(ctx, t0, t1, 0);
1240 tcg_temp_free(t1);
79aceca5 1241 } else {
74637406
AJ
1242 tcg_gen_sub_tl(t0, arg2, arg1);
1243 if (compute_ca) {
1244 gen_op_arith_compute_ca(ctx, t0, arg2, 1);
1245 }
1246 }
1247 if (compute_ov) {
1248 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1249 }
1250
1251 if (unlikely(Rc(ctx->opcode) != 0))
1252 gen_set_Rc0(ctx, t0);
1253
a7812ae4 1254 if (!TCGV_EQUAL(t0, ret)) {
74637406
AJ
1255 tcg_gen_mov_tl(ret, t0);
1256 tcg_temp_free(t0);
79aceca5 1257 }
79aceca5 1258}
74637406
AJ
1259/* Sub functions with Two operands functions */
1260#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
99e300ef 1261static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
1262{ \
1263 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1264 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1265 add_ca, compute_ca, compute_ov); \
1266}
1267/* Sub functions with one operand and one immediate */
1268#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
1269 add_ca, compute_ca, compute_ov) \
99e300ef 1270static void glue(gen_, name)(DisasContext *ctx) \
74637406
AJ
1271{ \
1272 TCGv t0 = tcg_const_local_tl(const_val); \
1273 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1274 cpu_gpr[rA(ctx->opcode)], t0, \
1275 add_ca, compute_ca, compute_ov); \
1276 tcg_temp_free(t0); \
1277}
1278/* subf subf. subfo subfo. */
1279GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1280GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1281/* subfc subfc. subfco subfco. */
1282GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1283GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1284/* subfe subfe. subfeo subfo. */
1285GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1286GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1287/* subfme subfme. subfmeo subfmeo. */
1288GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1289GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1290/* subfze subfze. subfzeo subfzeo.*/
1291GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1292GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
99e300ef 1293
54623277 1294/* subfic */
99e300ef 1295static void gen_subfic(DisasContext *ctx)
79aceca5 1296{
74637406
AJ
1297 /* Start with XER CA and OV disabled, the most likely case */
1298 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
a7812ae4 1299 TCGv t0 = tcg_temp_local_new();
74637406
AJ
1300 TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
1301 tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
1302 gen_op_arith_compute_ca(ctx, t0, t1, 1);
1303 tcg_temp_free(t1);
1304 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
1305 tcg_temp_free(t0);
79aceca5
FB
1306}
1307
79aceca5 1308/*** Integer logical ***/
26d67362 1309#define GEN_LOGICAL2(name, tcg_op, opc, type) \
99e300ef 1310static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 1311{ \
26d67362
AJ
1312 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \
1313 cpu_gpr[rB(ctx->opcode)]); \
76a66253 1314 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 1315 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5 1316}
79aceca5 1317
26d67362 1318#define GEN_LOGICAL1(name, tcg_op, opc, type) \
99e300ef 1319static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 1320{ \
26d67362 1321 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \
76a66253 1322 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 1323 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5
FB
1324}
1325
1326/* and & and. */
26d67362 1327GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
79aceca5 1328/* andc & andc. */
26d67362 1329GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
e8eaa2c0 1330
54623277 1331/* andi. */
e8eaa2c0 1332static void gen_andi_(DisasContext *ctx)
79aceca5 1333{
26d67362
AJ
1334 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1335 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1336}
e8eaa2c0 1337
54623277 1338/* andis. */
e8eaa2c0 1339static void gen_andis_(DisasContext *ctx)
79aceca5 1340{
26d67362
AJ
1341 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1342 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1343}
99e300ef 1344
54623277 1345/* cntlzw */
99e300ef 1346static void gen_cntlzw(DisasContext *ctx)
26d67362 1347{
a7812ae4 1348 gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
26d67362 1349 if (unlikely(Rc(ctx->opcode) != 0))
2e31f5d3 1350 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
26d67362 1351}
79aceca5 1352/* eqv & eqv. */
26d67362 1353GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
79aceca5 1354/* extsb & extsb. */
26d67362 1355GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
79aceca5 1356/* extsh & extsh. */
26d67362 1357GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
79aceca5 1358/* nand & nand. */
26d67362 1359GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
79aceca5 1360/* nor & nor. */
26d67362 1361GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
99e300ef 1362
54623277 1363/* or & or. */
99e300ef 1364static void gen_or(DisasContext *ctx)
9a64fbe4 1365{
76a66253
JM
1366 int rs, ra, rb;
1367
1368 rs = rS(ctx->opcode);
1369 ra = rA(ctx->opcode);
1370 rb = rB(ctx->opcode);
1371 /* Optimisation for mr. ri case */
1372 if (rs != ra || rs != rb) {
26d67362
AJ
1373 if (rs != rb)
1374 tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1375 else
1376 tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
76a66253 1377 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1378 gen_set_Rc0(ctx, cpu_gpr[ra]);
76a66253 1379 } else if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 1380 gen_set_Rc0(ctx, cpu_gpr[rs]);
c80f84e3
JM
1381#if defined(TARGET_PPC64)
1382 } else {
26d67362
AJ
1383 int prio = 0;
1384
c80f84e3
JM
1385 switch (rs) {
1386 case 1:
1387 /* Set process priority to low */
26d67362 1388 prio = 2;
c80f84e3
JM
1389 break;
1390 case 6:
1391 /* Set process priority to medium-low */
26d67362 1392 prio = 3;
c80f84e3
JM
1393 break;
1394 case 2:
1395 /* Set process priority to normal */
26d67362 1396 prio = 4;
c80f84e3 1397 break;
be147d08
JM
1398#if !defined(CONFIG_USER_ONLY)
1399 case 31:
76db3ba4 1400 if (ctx->mem_idx > 0) {
be147d08 1401 /* Set process priority to very low */
26d67362 1402 prio = 1;
be147d08
JM
1403 }
1404 break;
1405 case 5:
76db3ba4 1406 if (ctx->mem_idx > 0) {
be147d08 1407 /* Set process priority to medium-hight */
26d67362 1408 prio = 5;
be147d08
JM
1409 }
1410 break;
1411 case 3:
76db3ba4 1412 if (ctx->mem_idx > 0) {
be147d08 1413 /* Set process priority to high */
26d67362 1414 prio = 6;
be147d08
JM
1415 }
1416 break;
be147d08 1417 case 7:
76db3ba4 1418 if (ctx->mem_idx > 1) {
be147d08 1419 /* Set process priority to very high */
26d67362 1420 prio = 7;
be147d08
JM
1421 }
1422 break;
be147d08 1423#endif
c80f84e3
JM
1424 default:
1425 /* nop */
1426 break;
1427 }
26d67362 1428 if (prio) {
a7812ae4 1429 TCGv t0 = tcg_temp_new();
54cdcae6 1430 gen_load_spr(t0, SPR_PPR);
ea363694
AJ
1431 tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1432 tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
54cdcae6 1433 gen_store_spr(SPR_PPR, t0);
ea363694 1434 tcg_temp_free(t0);
26d67362 1435 }
c80f84e3 1436#endif
9a64fbe4 1437 }
9a64fbe4 1438}
79aceca5 1439/* orc & orc. */
26d67362 1440GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
99e300ef 1441
54623277 1442/* xor & xor. */
99e300ef 1443static void gen_xor(DisasContext *ctx)
9a64fbe4 1444{
9a64fbe4 1445 /* Optimisation for "set to zero" case */
26d67362 1446 if (rS(ctx->opcode) != rB(ctx->opcode))
312179c4 1447 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1448 else
1449 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
76a66253 1450 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1451 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
9a64fbe4 1452}
99e300ef 1453
54623277 1454/* ori */
99e300ef 1455static void gen_ori(DisasContext *ctx)
79aceca5 1456{
76a66253 1457 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 1458
9a64fbe4
FB
1459 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1460 /* NOP */
76a66253 1461 /* XXX: should handle special NOPs for POWER series */
9a64fbe4 1462 return;
76a66253 1463 }
26d67362 1464 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5 1465}
99e300ef 1466
54623277 1467/* oris */
99e300ef 1468static void gen_oris(DisasContext *ctx)
79aceca5 1469{
76a66253 1470 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 1471
9a64fbe4
FB
1472 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1473 /* NOP */
1474 return;
76a66253 1475 }
26d67362 1476 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
79aceca5 1477}
99e300ef 1478
54623277 1479/* xori */
99e300ef 1480static void gen_xori(DisasContext *ctx)
79aceca5 1481{
76a66253 1482 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
1483
1484 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1485 /* NOP */
1486 return;
1487 }
26d67362 1488 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5 1489}
99e300ef 1490
54623277 1491/* xoris */
99e300ef 1492static void gen_xoris(DisasContext *ctx)
79aceca5 1493{
76a66253 1494 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
1495
1496 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1497 /* NOP */
1498 return;
1499 }
26d67362 1500 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
79aceca5 1501}
99e300ef 1502
54623277 1503/* popcntb : PowerPC 2.03 specification */
99e300ef 1504static void gen_popcntb(DisasContext *ctx)
d9bce9d9 1505{
eaabeef2
DG
1506 gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1507}
1508
1509static void gen_popcntw(DisasContext *ctx)
1510{
1511 gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1512}
1513
d9bce9d9 1514#if defined(TARGET_PPC64)
eaabeef2
DG
1515/* popcntd: PowerPC 2.06 specification */
1516static void gen_popcntd(DisasContext *ctx)
1517{
1518 gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
d9bce9d9 1519}
eaabeef2 1520#endif
d9bce9d9
JM
1521
1522#if defined(TARGET_PPC64)
1523/* extsw & extsw. */
26d67362 1524GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
99e300ef 1525
54623277 1526/* cntlzd */
99e300ef 1527static void gen_cntlzd(DisasContext *ctx)
26d67362 1528{
a7812ae4 1529 gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
26d67362
AJ
1530 if (unlikely(Rc(ctx->opcode) != 0))
1531 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1532}
d9bce9d9
JM
1533#endif
1534
79aceca5 1535/*** Integer rotate ***/
99e300ef 1536
54623277 1537/* rlwimi & rlwimi. */
99e300ef 1538static void gen_rlwimi(DisasContext *ctx)
79aceca5 1539{
76a66253 1540 uint32_t mb, me, sh;
79aceca5
FB
1541
1542 mb = MB(ctx->opcode);
1543 me = ME(ctx->opcode);
76a66253 1544 sh = SH(ctx->opcode);
d03ef511
AJ
1545 if (likely(sh == 0 && mb == 0 && me == 31)) {
1546 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1547 } else {
d03ef511 1548 target_ulong mask;
a7812ae4
PB
1549 TCGv t1;
1550 TCGv t0 = tcg_temp_new();
54843a58 1551#if defined(TARGET_PPC64)
a7812ae4
PB
1552 TCGv_i32 t2 = tcg_temp_new_i32();
1553 tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
1554 tcg_gen_rotli_i32(t2, t2, sh);
1555 tcg_gen_extu_i32_i64(t0, t2);
1556 tcg_temp_free_i32(t2);
54843a58
AJ
1557#else
1558 tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1559#endif
76a66253 1560#if defined(TARGET_PPC64)
d03ef511
AJ
1561 mb += 32;
1562 me += 32;
76a66253 1563#endif
d03ef511 1564 mask = MASK(mb, me);
a7812ae4 1565 t1 = tcg_temp_new();
d03ef511
AJ
1566 tcg_gen_andi_tl(t0, t0, mask);
1567 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1568 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1569 tcg_temp_free(t0);
1570 tcg_temp_free(t1);
1571 }
76a66253 1572 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1573 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1574}
99e300ef 1575
54623277 1576/* rlwinm & rlwinm. */
99e300ef 1577static void gen_rlwinm(DisasContext *ctx)
79aceca5
FB
1578{
1579 uint32_t mb, me, sh;
3b46e624 1580
79aceca5
FB
1581 sh = SH(ctx->opcode);
1582 mb = MB(ctx->opcode);
1583 me = ME(ctx->opcode);
d03ef511
AJ
1584
1585 if (likely(mb == 0 && me == (31 - sh))) {
1586 if (likely(sh == 0)) {
1587 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1588 } else {
a7812ae4 1589 TCGv t0 = tcg_temp_new();
d03ef511
AJ
1590 tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1591 tcg_gen_shli_tl(t0, t0, sh);
1592 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1593 tcg_temp_free(t0);
79aceca5 1594 }
d03ef511 1595 } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
a7812ae4 1596 TCGv t0 = tcg_temp_new();
d03ef511
AJ
1597 tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1598 tcg_gen_shri_tl(t0, t0, mb);
1599 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1600 tcg_temp_free(t0);
1601 } else {
a7812ae4 1602 TCGv t0 = tcg_temp_new();
54843a58 1603#if defined(TARGET_PPC64)
a7812ae4 1604 TCGv_i32 t1 = tcg_temp_new_i32();
54843a58
AJ
1605 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1606 tcg_gen_rotli_i32(t1, t1, sh);
1607 tcg_gen_extu_i32_i64(t0, t1);
a7812ae4 1608 tcg_temp_free_i32(t1);
54843a58
AJ
1609#else
1610 tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1611#endif
76a66253 1612#if defined(TARGET_PPC64)
d03ef511
AJ
1613 mb += 32;
1614 me += 32;
76a66253 1615#endif
d03ef511
AJ
1616 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1617 tcg_temp_free(t0);
1618 }
76a66253 1619 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1620 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1621}
99e300ef 1622
54623277 1623/* rlwnm & rlwnm. */
99e300ef 1624static void gen_rlwnm(DisasContext *ctx)
79aceca5
FB
1625{
1626 uint32_t mb, me;
54843a58
AJ
1627 TCGv t0;
1628#if defined(TARGET_PPC64)
a7812ae4 1629 TCGv_i32 t1, t2;
54843a58 1630#endif
79aceca5
FB
1631
1632 mb = MB(ctx->opcode);
1633 me = ME(ctx->opcode);
a7812ae4 1634 t0 = tcg_temp_new();
d03ef511 1635 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
54843a58 1636#if defined(TARGET_PPC64)
a7812ae4
PB
1637 t1 = tcg_temp_new_i32();
1638 t2 = tcg_temp_new_i32();
54843a58
AJ
1639 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1640 tcg_gen_trunc_i64_i32(t2, t0);
1641 tcg_gen_rotl_i32(t1, t1, t2);
1642 tcg_gen_extu_i32_i64(t0, t1);
a7812ae4
PB
1643 tcg_temp_free_i32(t1);
1644 tcg_temp_free_i32(t2);
54843a58
AJ
1645#else
1646 tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
1647#endif
76a66253
JM
1648 if (unlikely(mb != 0 || me != 31)) {
1649#if defined(TARGET_PPC64)
1650 mb += 32;
1651 me += 32;
1652#endif
54843a58 1653 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
d03ef511 1654 } else {
54843a58 1655 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
79aceca5 1656 }
54843a58 1657 tcg_temp_free(t0);
76a66253 1658 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1659 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5
FB
1660}
1661
d9bce9d9
JM
1662#if defined(TARGET_PPC64)
1663#define GEN_PPC64_R2(name, opc1, opc2) \
e8eaa2c0 1664static void glue(gen_, name##0)(DisasContext *ctx) \
d9bce9d9
JM
1665{ \
1666 gen_##name(ctx, 0); \
1667} \
e8eaa2c0
BS
1668 \
1669static void glue(gen_, name##1)(DisasContext *ctx) \
d9bce9d9
JM
1670{ \
1671 gen_##name(ctx, 1); \
1672}
1673#define GEN_PPC64_R4(name, opc1, opc2) \
e8eaa2c0 1674static void glue(gen_, name##0)(DisasContext *ctx) \
d9bce9d9
JM
1675{ \
1676 gen_##name(ctx, 0, 0); \
1677} \
e8eaa2c0
BS
1678 \
1679static void glue(gen_, name##1)(DisasContext *ctx) \
d9bce9d9
JM
1680{ \
1681 gen_##name(ctx, 0, 1); \
1682} \
e8eaa2c0
BS
1683 \
1684static void glue(gen_, name##2)(DisasContext *ctx) \
d9bce9d9
JM
1685{ \
1686 gen_##name(ctx, 1, 0); \
1687} \
e8eaa2c0
BS
1688 \
1689static void glue(gen_, name##3)(DisasContext *ctx) \
d9bce9d9
JM
1690{ \
1691 gen_##name(ctx, 1, 1); \
1692}
51789c41 1693
636aa200
BS
1694static inline void gen_rldinm(DisasContext *ctx, uint32_t mb, uint32_t me,
1695 uint32_t sh)
51789c41 1696{
d03ef511
AJ
1697 if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
1698 tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1699 } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
1700 tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
1701 } else {
a7812ae4 1702 TCGv t0 = tcg_temp_new();
54843a58 1703 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
d03ef511 1704 if (likely(mb == 0 && me == 63)) {
54843a58 1705 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
d03ef511
AJ
1706 } else {
1707 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
51789c41 1708 }
d03ef511 1709 tcg_temp_free(t0);
51789c41 1710 }
51789c41 1711 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1712 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
51789c41 1713}
d9bce9d9 1714/* rldicl - rldicl. */
636aa200 1715static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn)
d9bce9d9 1716{
51789c41 1717 uint32_t sh, mb;
d9bce9d9 1718
9d53c753
JM
1719 sh = SH(ctx->opcode) | (shn << 5);
1720 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 1721 gen_rldinm(ctx, mb, 63, sh);
d9bce9d9 1722}
51789c41 1723GEN_PPC64_R4(rldicl, 0x1E, 0x00);
d9bce9d9 1724/* rldicr - rldicr. */
636aa200 1725static inline void gen_rldicr(DisasContext *ctx, int men, int shn)
d9bce9d9 1726{
51789c41 1727 uint32_t sh, me;
d9bce9d9 1728
9d53c753
JM
1729 sh = SH(ctx->opcode) | (shn << 5);
1730 me = MB(ctx->opcode) | (men << 5);
51789c41 1731 gen_rldinm(ctx, 0, me, sh);
d9bce9d9 1732}
51789c41 1733GEN_PPC64_R4(rldicr, 0x1E, 0x02);
d9bce9d9 1734/* rldic - rldic. */
636aa200 1735static inline void gen_rldic(DisasContext *ctx, int mbn, int shn)
d9bce9d9 1736{
51789c41 1737 uint32_t sh, mb;
d9bce9d9 1738
9d53c753
JM
1739 sh = SH(ctx->opcode) | (shn << 5);
1740 mb = MB(ctx->opcode) | (mbn << 5);
51789c41
JM
1741 gen_rldinm(ctx, mb, 63 - sh, sh);
1742}
1743GEN_PPC64_R4(rldic, 0x1E, 0x04);
1744
636aa200 1745static inline void gen_rldnm(DisasContext *ctx, uint32_t mb, uint32_t me)
51789c41 1746{
54843a58 1747 TCGv t0;
d03ef511
AJ
1748
1749 mb = MB(ctx->opcode);
1750 me = ME(ctx->opcode);
a7812ae4 1751 t0 = tcg_temp_new();
d03ef511 1752 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
54843a58 1753 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
51789c41 1754 if (unlikely(mb != 0 || me != 63)) {
54843a58
AJ
1755 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1756 } else {
1757 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1758 }
1759 tcg_temp_free(t0);
51789c41 1760 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1761 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
d9bce9d9 1762}
51789c41 1763
d9bce9d9 1764/* rldcl - rldcl. */
636aa200 1765static inline void gen_rldcl(DisasContext *ctx, int mbn)
d9bce9d9 1766{
51789c41 1767 uint32_t mb;
d9bce9d9 1768
9d53c753 1769 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 1770 gen_rldnm(ctx, mb, 63);
d9bce9d9 1771}
36081602 1772GEN_PPC64_R2(rldcl, 0x1E, 0x08);
d9bce9d9 1773/* rldcr - rldcr. */
636aa200 1774static inline void gen_rldcr(DisasContext *ctx, int men)
d9bce9d9 1775{
51789c41 1776 uint32_t me;
d9bce9d9 1777
9d53c753 1778 me = MB(ctx->opcode) | (men << 5);
51789c41 1779 gen_rldnm(ctx, 0, me);
d9bce9d9 1780}
36081602 1781GEN_PPC64_R2(rldcr, 0x1E, 0x09);
d9bce9d9 1782/* rldimi - rldimi. */
636aa200 1783static inline void gen_rldimi(DisasContext *ctx, int mbn, int shn)
d9bce9d9 1784{
271a916e 1785 uint32_t sh, mb, me;
d9bce9d9 1786
9d53c753
JM
1787 sh = SH(ctx->opcode) | (shn << 5);
1788 mb = MB(ctx->opcode) | (mbn << 5);
271a916e 1789 me = 63 - sh;
d03ef511
AJ
1790 if (unlikely(sh == 0 && mb == 0)) {
1791 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1792 } else {
1793 TCGv t0, t1;
1794 target_ulong mask;
1795
a7812ae4 1796 t0 = tcg_temp_new();
54843a58 1797 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
a7812ae4 1798 t1 = tcg_temp_new();
d03ef511
AJ
1799 mask = MASK(mb, me);
1800 tcg_gen_andi_tl(t0, t0, mask);
1801 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1802 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1803 tcg_temp_free(t0);
1804 tcg_temp_free(t1);
51789c41 1805 }
51789c41 1806 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1807 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
d9bce9d9 1808}
36081602 1809GEN_PPC64_R4(rldimi, 0x1E, 0x06);
d9bce9d9
JM
1810#endif
1811
79aceca5 1812/*** Integer shift ***/
99e300ef 1813
54623277 1814/* slw & slw. */
99e300ef 1815static void gen_slw(DisasContext *ctx)
26d67362 1816{
7fd6bf7d 1817 TCGv t0, t1;
26d67362 1818
7fd6bf7d
AJ
1819 t0 = tcg_temp_new();
1820 /* AND rS with a mask that is 0 when rB >= 0x20 */
1821#if defined(TARGET_PPC64)
1822 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1823 tcg_gen_sari_tl(t0, t0, 0x3f);
1824#else
1825 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1826 tcg_gen_sari_tl(t0, t0, 0x1f);
1827#endif
1828 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1829 t1 = tcg_temp_new();
1830 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1831 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1832 tcg_temp_free(t1);
fea0c503 1833 tcg_temp_free(t0);
7fd6bf7d 1834 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
26d67362
AJ
1835 if (unlikely(Rc(ctx->opcode) != 0))
1836 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1837}
99e300ef 1838
54623277 1839/* sraw & sraw. */
99e300ef 1840static void gen_sraw(DisasContext *ctx)
26d67362 1841{
a7812ae4
PB
1842 gen_helper_sraw(cpu_gpr[rA(ctx->opcode)],
1843 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1844 if (unlikely(Rc(ctx->opcode) != 0))
1845 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1846}
99e300ef 1847
54623277 1848/* srawi & srawi. */
99e300ef 1849static void gen_srawi(DisasContext *ctx)
79aceca5 1850{
26d67362
AJ
1851 int sh = SH(ctx->opcode);
1852 if (sh != 0) {
1853 int l1, l2;
fea0c503 1854 TCGv t0;
26d67362
AJ
1855 l1 = gen_new_label();
1856 l2 = gen_new_label();
a7812ae4 1857 t0 = tcg_temp_local_new();
fea0c503
AJ
1858 tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1859 tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
1860 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1861 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
269f3e95 1862 tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
26d67362
AJ
1863 tcg_gen_br(l2);
1864 gen_set_label(l1);
269f3e95 1865 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
26d67362 1866 gen_set_label(l2);
fea0c503
AJ
1867 tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1868 tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
1869 tcg_temp_free(t0);
26d67362
AJ
1870 } else {
1871 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
269f3e95 1872 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
d9bce9d9 1873 }
76a66253 1874 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1875 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1876}
99e300ef 1877
54623277 1878/* srw & srw. */
99e300ef 1879static void gen_srw(DisasContext *ctx)
26d67362 1880{
fea0c503 1881 TCGv t0, t1;
d9bce9d9 1882
7fd6bf7d
AJ
1883 t0 = tcg_temp_new();
1884 /* AND rS with a mask that is 0 when rB >= 0x20 */
1885#if defined(TARGET_PPC64)
1886 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a);
1887 tcg_gen_sari_tl(t0, t0, 0x3f);
1888#else
1889 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a);
1890 tcg_gen_sari_tl(t0, t0, 0x1f);
1891#endif
1892 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1893 tcg_gen_ext32u_tl(t0, t0);
a7812ae4 1894 t1 = tcg_temp_new();
7fd6bf7d
AJ
1895 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f);
1896 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
fea0c503 1897 tcg_temp_free(t1);
fea0c503 1898 tcg_temp_free(t0);
26d67362
AJ
1899 if (unlikely(Rc(ctx->opcode) != 0))
1900 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1901}
54623277 1902
d9bce9d9
JM
1903#if defined(TARGET_PPC64)
1904/* sld & sld. */
99e300ef 1905static void gen_sld(DisasContext *ctx)
26d67362 1906{
7fd6bf7d 1907 TCGv t0, t1;
26d67362 1908
7fd6bf7d
AJ
1909 t0 = tcg_temp_new();
1910 /* AND rS with a mask that is 0 when rB >= 0x40 */
1911 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1912 tcg_gen_sari_tl(t0, t0, 0x3f);
1913 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1914 t1 = tcg_temp_new();
1915 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
1916 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1917 tcg_temp_free(t1);
fea0c503 1918 tcg_temp_free(t0);
26d67362
AJ
1919 if (unlikely(Rc(ctx->opcode) != 0))
1920 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1921}
99e300ef 1922
54623277 1923/* srad & srad. */
99e300ef 1924static void gen_srad(DisasContext *ctx)
26d67362 1925{
a7812ae4
PB
1926 gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
1927 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1928 if (unlikely(Rc(ctx->opcode) != 0))
1929 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1930}
d9bce9d9 1931/* sradi & sradi. */
636aa200 1932static inline void gen_sradi(DisasContext *ctx, int n)
d9bce9d9 1933{
26d67362 1934 int sh = SH(ctx->opcode) + (n << 5);
d9bce9d9 1935 if (sh != 0) {
26d67362 1936 int l1, l2;
fea0c503 1937 TCGv t0;
26d67362
AJ
1938 l1 = gen_new_label();
1939 l2 = gen_new_label();
a7812ae4 1940 t0 = tcg_temp_local_new();
26d67362 1941 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
fea0c503
AJ
1942 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1943 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
269f3e95 1944 tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
26d67362
AJ
1945 tcg_gen_br(l2);
1946 gen_set_label(l1);
269f3e95 1947 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
26d67362 1948 gen_set_label(l2);
a9730017 1949 tcg_temp_free(t0);
26d67362
AJ
1950 tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1951 } else {
1952 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
269f3e95 1953 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
d9bce9d9 1954 }
d9bce9d9 1955 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1956 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
d9bce9d9 1957}
e8eaa2c0
BS
1958
1959static void gen_sradi0(DisasContext *ctx)
d9bce9d9
JM
1960{
1961 gen_sradi(ctx, 0);
1962}
e8eaa2c0
BS
1963
1964static void gen_sradi1(DisasContext *ctx)
d9bce9d9
JM
1965{
1966 gen_sradi(ctx, 1);
1967}
99e300ef 1968
54623277 1969/* srd & srd. */
99e300ef 1970static void gen_srd(DisasContext *ctx)
26d67362 1971{
7fd6bf7d 1972 TCGv t0, t1;
26d67362 1973
7fd6bf7d
AJ
1974 t0 = tcg_temp_new();
1975 /* AND rS with a mask that is 0 when rB >= 0x40 */
1976 tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39);
1977 tcg_gen_sari_tl(t0, t0, 0x3f);
1978 tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
1979 t1 = tcg_temp_new();
1980 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f);
1981 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1982 tcg_temp_free(t1);
fea0c503 1983 tcg_temp_free(t0);
26d67362
AJ
1984 if (unlikely(Rc(ctx->opcode) != 0))
1985 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1986}
d9bce9d9 1987#endif
79aceca5
FB
1988
1989/*** Floating-Point arithmetic ***/
7c58044c 1990#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
99e300ef 1991static void gen_f##name(DisasContext *ctx) \
9a64fbe4 1992{ \
76a66253 1993 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 1994 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
1995 return; \
1996 } \
eb44b959
AJ
1997 /* NIP cannot be restored if the memory exception comes from an helper */ \
1998 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 1999 gen_reset_fpstatus(); \
af12906f
AJ
2000 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2001 cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
4ecc3190 2002 if (isfloat) { \
af12906f 2003 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2004 } \
af12906f
AJ
2005 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf, \
2006 Rc(ctx->opcode) != 0); \
9a64fbe4
FB
2007}
2008
7c58044c
JM
2009#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
2010_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
2011_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
9a64fbe4 2012
7c58044c 2013#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
99e300ef 2014static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2015{ \
76a66253 2016 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2017 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2018 return; \
2019 } \
eb44b959
AJ
2020 /* NIP cannot be restored if the memory exception comes from an helper */ \
2021 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2022 gen_reset_fpstatus(); \
af12906f
AJ
2023 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2024 cpu_fpr[rB(ctx->opcode)]); \
4ecc3190 2025 if (isfloat) { \
af12906f 2026 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2027 } \
af12906f
AJ
2028 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2029 set_fprf, Rc(ctx->opcode) != 0); \
9a64fbe4 2030}
7c58044c
JM
2031#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
2032_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2033_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
9a64fbe4 2034
7c58044c 2035#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
99e300ef 2036static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2037{ \
76a66253 2038 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2039 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2040 return; \
2041 } \
eb44b959
AJ
2042 /* NIP cannot be restored if the memory exception comes from an helper */ \
2043 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2044 gen_reset_fpstatus(); \
af12906f
AJ
2045 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2046 cpu_fpr[rC(ctx->opcode)]); \
4ecc3190 2047 if (isfloat) { \
af12906f 2048 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2049 } \
af12906f
AJ
2050 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2051 set_fprf, Rc(ctx->opcode) != 0); \
9a64fbe4 2052}
7c58044c
JM
2053#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
2054_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2055_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
9a64fbe4 2056
7c58044c 2057#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
99e300ef 2058static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2059{ \
76a66253 2060 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2061 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2062 return; \
2063 } \
eb44b959
AJ
2064 /* NIP cannot be restored if the memory exception comes from an helper */ \
2065 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2066 gen_reset_fpstatus(); \
af12906f
AJ
2067 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
2068 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2069 set_fprf, Rc(ctx->opcode) != 0); \
79aceca5
FB
2070}
2071
7c58044c 2072#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
99e300ef 2073static void gen_f##name(DisasContext *ctx) \
9a64fbe4 2074{ \
76a66253 2075 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 2076 gen_exception(ctx, POWERPC_EXCP_FPU); \
3cc62370
FB
2077 return; \
2078 } \
eb44b959
AJ
2079 /* NIP cannot be restored if the memory exception comes from an helper */ \
2080 gen_update_nip(ctx, ctx->nip - 4); \
7c58044c 2081 gen_reset_fpstatus(); \
af12906f
AJ
2082 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
2083 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2084 set_fprf, Rc(ctx->opcode) != 0); \
79aceca5
FB
2085}
2086
9a64fbe4 2087/* fadd - fadds */
7c58044c 2088GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
4ecc3190 2089/* fdiv - fdivs */
7c58044c 2090GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
4ecc3190 2091/* fmul - fmuls */
7c58044c 2092GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
79aceca5 2093
d7e4b87e 2094/* fre */
7c58044c 2095GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
d7e4b87e 2096
a750fc0b 2097/* fres */
7c58044c 2098GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
79aceca5 2099
a750fc0b 2100/* frsqrte */
7c58044c
JM
2101GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2102
2103/* frsqrtes */
99e300ef 2104static void gen_frsqrtes(DisasContext *ctx)
7c58044c 2105{
af12906f 2106 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2107 gen_exception(ctx, POWERPC_EXCP_FPU);
af12906f
AJ
2108 return;
2109 }
eb44b959
AJ
2110 /* NIP cannot be restored if the memory exception comes from an helper */
2111 gen_update_nip(ctx, ctx->nip - 4);
af12906f
AJ
2112 gen_reset_fpstatus();
2113 gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2114 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2115 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
7c58044c 2116}
79aceca5 2117
a750fc0b 2118/* fsel */
7c58044c 2119_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
4ecc3190 2120/* fsub - fsubs */
7c58044c 2121GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
79aceca5 2122/* Optional: */
99e300ef 2123
54623277 2124/* fsqrt */
99e300ef 2125static void gen_fsqrt(DisasContext *ctx)
c7d344af 2126{
76a66253 2127 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2128 gen_exception(ctx, POWERPC_EXCP_FPU);
c7d344af
FB
2129 return;
2130 }
eb44b959
AJ
2131 /* NIP cannot be restored if the memory exception comes from an helper */
2132 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2133 gen_reset_fpstatus();
af12906f
AJ
2134 gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2135 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
c7d344af 2136}
79aceca5 2137
99e300ef 2138static void gen_fsqrts(DisasContext *ctx)
79aceca5 2139{
76a66253 2140 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2141 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2142 return;
2143 }
eb44b959
AJ
2144 /* NIP cannot be restored if the memory exception comes from an helper */
2145 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2146 gen_reset_fpstatus();
af12906f
AJ
2147 gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2148 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2149 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
79aceca5
FB
2150}
2151
2152/*** Floating-Point multiply-and-add ***/
4ecc3190 2153/* fmadd - fmadds */
7c58044c 2154GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
4ecc3190 2155/* fmsub - fmsubs */
7c58044c 2156GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
4ecc3190 2157/* fnmadd - fnmadds */
7c58044c 2158GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
4ecc3190 2159/* fnmsub - fnmsubs */
7c58044c 2160GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
79aceca5
FB
2161
2162/*** Floating-Point round & convert ***/
2163/* fctiw */
7c58044c 2164GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
79aceca5 2165/* fctiwz */
7c58044c 2166GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
79aceca5 2167/* frsp */
7c58044c 2168GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
426613db
JM
2169#if defined(TARGET_PPC64)
2170/* fcfid */
7c58044c 2171GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
426613db 2172/* fctid */
7c58044c 2173GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
426613db 2174/* fctidz */
7c58044c 2175GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
426613db 2176#endif
79aceca5 2177
d7e4b87e 2178/* frin */
7c58044c 2179GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
d7e4b87e 2180/* friz */
7c58044c 2181GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
d7e4b87e 2182/* frip */
7c58044c 2183GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
d7e4b87e 2184/* frim */
7c58044c 2185GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
d7e4b87e 2186
79aceca5 2187/*** Floating-Point compare ***/
99e300ef 2188
54623277 2189/* fcmpo */
99e300ef 2190static void gen_fcmpo(DisasContext *ctx)
79aceca5 2191{
330c483b 2192 TCGv_i32 crf;
76a66253 2193 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2194 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2195 return;
2196 }
eb44b959
AJ
2197 /* NIP cannot be restored if the memory exception comes from an helper */
2198 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2199 gen_reset_fpstatus();
9a819377
AJ
2200 crf = tcg_const_i32(crfD(ctx->opcode));
2201 gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
330c483b 2202 tcg_temp_free_i32(crf);
af12906f 2203 gen_helper_float_check_status();
79aceca5
FB
2204}
2205
2206/* fcmpu */
99e300ef 2207static void gen_fcmpu(DisasContext *ctx)
79aceca5 2208{
330c483b 2209 TCGv_i32 crf;
76a66253 2210 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2211 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2212 return;
2213 }
eb44b959
AJ
2214 /* NIP cannot be restored if the memory exception comes from an helper */
2215 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2216 gen_reset_fpstatus();
9a819377
AJ
2217 crf = tcg_const_i32(crfD(ctx->opcode));
2218 gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf);
330c483b 2219 tcg_temp_free_i32(crf);
af12906f 2220 gen_helper_float_check_status();
79aceca5
FB
2221}
2222
9a64fbe4
FB
2223/*** Floating-point move ***/
2224/* fabs */
7c58044c
JM
2225/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2226GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
9a64fbe4
FB
2227
2228/* fmr - fmr. */
7c58044c 2229/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
99e300ef 2230static void gen_fmr(DisasContext *ctx)
9a64fbe4 2231{
76a66253 2232 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2233 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2234 return;
2235 }
af12906f
AJ
2236 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2237 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
9a64fbe4
FB
2238}
2239
2240/* fnabs */
7c58044c
JM
2241/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2242GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
9a64fbe4 2243/* fneg */
7c58044c
JM
2244/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2245GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
9a64fbe4 2246
79aceca5 2247/*** Floating-Point status & ctrl register ***/
99e300ef 2248
54623277 2249/* mcrfs */
99e300ef 2250static void gen_mcrfs(DisasContext *ctx)
79aceca5 2251{
7c58044c
JM
2252 int bfa;
2253
76a66253 2254 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2255 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2256 return;
2257 }
7c58044c 2258 bfa = 4 * (7 - crfS(ctx->opcode));
e1571908
AJ
2259 tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
2260 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
af12906f 2261 tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
79aceca5
FB
2262}
2263
2264/* mffs */
99e300ef 2265static void gen_mffs(DisasContext *ctx)
79aceca5 2266{
76a66253 2267 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2268 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2269 return;
2270 }
7c58044c 2271 gen_reset_fpstatus();
af12906f
AJ
2272 tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2273 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
79aceca5
FB
2274}
2275
2276/* mtfsb0 */
99e300ef 2277static void gen_mtfsb0(DisasContext *ctx)
79aceca5 2278{
fb0eaffc 2279 uint8_t crb;
3b46e624 2280
76a66253 2281 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2282 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2283 return;
2284 }
6e35d524 2285 crb = 31 - crbD(ctx->opcode);
7c58044c 2286 gen_reset_fpstatus();
6e35d524 2287 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
eb44b959
AJ
2288 TCGv_i32 t0;
2289 /* NIP cannot be restored if the memory exception comes from an helper */
2290 gen_update_nip(ctx, ctx->nip - 4);
2291 t0 = tcg_const_i32(crb);
6e35d524
AJ
2292 gen_helper_fpscr_clrbit(t0);
2293 tcg_temp_free_i32(t0);
2294 }
7c58044c 2295 if (unlikely(Rc(ctx->opcode) != 0)) {
e1571908 2296 tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
7c58044c 2297 }
79aceca5
FB
2298}
2299
2300/* mtfsb1 */
99e300ef 2301static void gen_mtfsb1(DisasContext *ctx)
79aceca5 2302{
fb0eaffc 2303 uint8_t crb;
3b46e624 2304
76a66253 2305 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2306 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2307 return;
2308 }
6e35d524 2309 crb = 31 - crbD(ctx->opcode);
7c58044c
JM
2310 gen_reset_fpstatus();
2311 /* XXX: we pretend we can only do IEEE floating-point computations */
af12906f 2312 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
eb44b959
AJ
2313 TCGv_i32 t0;
2314 /* NIP cannot be restored if the memory exception comes from an helper */
2315 gen_update_nip(ctx, ctx->nip - 4);
2316 t0 = tcg_const_i32(crb);
af12906f 2317 gen_helper_fpscr_setbit(t0);
0f2f39c2 2318 tcg_temp_free_i32(t0);
af12906f 2319 }
7c58044c 2320 if (unlikely(Rc(ctx->opcode) != 0)) {
e1571908 2321 tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
7c58044c
JM
2322 }
2323 /* We can raise a differed exception */
af12906f 2324 gen_helper_float_check_status();
79aceca5
FB
2325}
2326
2327/* mtfsf */
99e300ef 2328static void gen_mtfsf(DisasContext *ctx)
79aceca5 2329{
0f2f39c2 2330 TCGv_i32 t0;
4911012d 2331 int L = ctx->opcode & 0x02000000;
af12906f 2332
76a66253 2333 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2334 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2335 return;
2336 }
eb44b959
AJ
2337 /* NIP cannot be restored if the memory exception comes from an helper */
2338 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2339 gen_reset_fpstatus();
4911012d
BS
2340 if (L)
2341 t0 = tcg_const_i32(0xff);
2342 else
2343 t0 = tcg_const_i32(FM(ctx->opcode));
af12906f 2344 gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
0f2f39c2 2345 tcg_temp_free_i32(t0);
7c58044c 2346 if (unlikely(Rc(ctx->opcode) != 0)) {
e1571908 2347 tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
7c58044c
JM
2348 }
2349 /* We can raise a differed exception */
af12906f 2350 gen_helper_float_check_status();
79aceca5
FB
2351}
2352
2353/* mtfsfi */
99e300ef 2354static void gen_mtfsfi(DisasContext *ctx)
79aceca5 2355{
7c58044c 2356 int bf, sh;
0f2f39c2
AJ
2357 TCGv_i64 t0;
2358 TCGv_i32 t1;
7c58044c 2359
76a66253 2360 if (unlikely(!ctx->fpu_enabled)) {
e06fcd75 2361 gen_exception(ctx, POWERPC_EXCP_FPU);
3cc62370
FB
2362 return;
2363 }
7c58044c
JM
2364 bf = crbD(ctx->opcode) >> 2;
2365 sh = 7 - bf;
eb44b959
AJ
2366 /* NIP cannot be restored if the memory exception comes from an helper */
2367 gen_update_nip(ctx, ctx->nip - 4);
7c58044c 2368 gen_reset_fpstatus();
0f2f39c2 2369 t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
af12906f
AJ
2370 t1 = tcg_const_i32(1 << sh);
2371 gen_helper_store_fpscr(t0, t1);
0f2f39c2
AJ
2372 tcg_temp_free_i64(t0);
2373 tcg_temp_free_i32(t1);
7c58044c 2374 if (unlikely(Rc(ctx->opcode) != 0)) {
e1571908 2375 tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
7c58044c
JM
2376 }
2377 /* We can raise a differed exception */
af12906f 2378 gen_helper_float_check_status();
79aceca5
FB
2379}
2380
76a66253
JM
2381/*** Addressing modes ***/
2382/* Register indirect with immediate index : EA = (rA|0) + SIMM */
636aa200
BS
2383static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
2384 target_long maskl)
76a66253
JM
2385{
2386 target_long simm = SIMM(ctx->opcode);
2387
be147d08 2388 simm &= ~maskl;
76db3ba4
AJ
2389 if (rA(ctx->opcode) == 0) {
2390#if defined(TARGET_PPC64)
2391 if (!ctx->sf_mode) {
2392 tcg_gen_movi_tl(EA, (uint32_t)simm);
2393 } else
2394#endif
e2be8d8d 2395 tcg_gen_movi_tl(EA, simm);
76db3ba4 2396 } else if (likely(simm != 0)) {
e2be8d8d 2397 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
76db3ba4
AJ
2398#if defined(TARGET_PPC64)
2399 if (!ctx->sf_mode) {
2400 tcg_gen_ext32u_tl(EA, EA);
2401 }
2402#endif
2403 } else {
2404#if defined(TARGET_PPC64)
2405 if (!ctx->sf_mode) {
2406 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2407 } else
2408#endif
e2be8d8d 2409 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
76db3ba4 2410 }
76a66253
JM
2411}
2412
636aa200 2413static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
76a66253 2414{
76db3ba4
AJ
2415 if (rA(ctx->opcode) == 0) {
2416#if defined(TARGET_PPC64)
2417 if (!ctx->sf_mode) {
2418 tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2419 } else
2420#endif
e2be8d8d 2421 tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
76db3ba4 2422 } else {
e2be8d8d 2423 tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76db3ba4
AJ
2424#if defined(TARGET_PPC64)
2425 if (!ctx->sf_mode) {
2426 tcg_gen_ext32u_tl(EA, EA);
2427 }
2428#endif
2429 }
76a66253
JM
2430}
2431
636aa200 2432static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
76a66253 2433{
76db3ba4 2434 if (rA(ctx->opcode) == 0) {
e2be8d8d 2435 tcg_gen_movi_tl(EA, 0);
76db3ba4
AJ
2436 } else {
2437#if defined(TARGET_PPC64)
2438 if (!ctx->sf_mode) {
2439 tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2440 } else
2441#endif
2442 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
2443 }
2444}
2445
636aa200
BS
2446static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
2447 target_long val)
76db3ba4
AJ
2448{
2449 tcg_gen_addi_tl(ret, arg1, val);
2450#if defined(TARGET_PPC64)
2451 if (!ctx->sf_mode) {
2452 tcg_gen_ext32u_tl(ret, ret);
2453 }
2454#endif
76a66253
JM
2455}
2456
636aa200 2457static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
cf360a32
AJ
2458{
2459 int l1 = gen_new_label();
2460 TCGv t0 = tcg_temp_new();
2461 TCGv_i32 t1, t2;
2462 /* NIP cannot be restored if the memory exception comes from an helper */
2463 gen_update_nip(ctx, ctx->nip - 4);
2464 tcg_gen_andi_tl(t0, EA, mask);
2465 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2466 t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2467 t2 = tcg_const_i32(0);
2468 gen_helper_raise_exception_err(t1, t2);
2469 tcg_temp_free_i32(t1);
2470 tcg_temp_free_i32(t2);
2471 gen_set_label(l1);
2472 tcg_temp_free(t0);
2473}
2474
7863667f 2475/*** Integer load ***/
636aa200 2476static inline void gen_qemu_ld8u(DisasContext *ctx, TCGv arg1, TCGv arg2)
76db3ba4
AJ
2477{
2478 tcg_gen_qemu_ld8u(arg1, arg2, ctx->mem_idx);
2479}
2480
636aa200 2481static inline void gen_qemu_ld8s(DisasContext *ctx, TCGv arg1, TCGv arg2)
76db3ba4
AJ
2482{
2483 tcg_gen_qemu_ld8s(arg1, arg2, ctx->mem_idx);
2484}
2485
636aa200 2486static inline void gen_qemu_ld16u(DisasContext *ctx, TCGv arg1, TCGv arg2)
76db3ba4
AJ
2487{
2488 tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2489 if (unlikely(ctx->le_mode)) {
fa3966a3 2490 tcg_gen_bswap16_tl(arg1, arg1);
76db3ba4 2491 }
b61f2753
AJ
2492}
2493
636aa200 2494static inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2495{
76db3ba4 2496 if (unlikely(ctx->le_mode)) {
76db3ba4 2497 tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
fa3966a3 2498 tcg_gen_bswap16_tl(arg1, arg1);
76db3ba4 2499 tcg_gen_ext16s_tl(arg1, arg1);
76db3ba4
AJ
2500 } else {
2501 tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
2502 }
b61f2753
AJ
2503}
2504
636aa200 2505static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2506{
76db3ba4
AJ
2507 tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2508 if (unlikely(ctx->le_mode)) {
fa3966a3 2509 tcg_gen_bswap32_tl(arg1, arg1);
76db3ba4 2510 }
b61f2753
AJ
2511}
2512
76db3ba4 2513#if defined(TARGET_PPC64)
636aa200 2514static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2515{
a457e7ee 2516 if (unlikely(ctx->le_mode)) {
76db3ba4 2517 tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
fa3966a3
AJ
2518 tcg_gen_bswap32_tl(arg1, arg1);
2519 tcg_gen_ext32s_tl(arg1, arg1);
b61f2753 2520 } else
76db3ba4 2521 tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
b61f2753 2522}
76db3ba4 2523#endif
b61f2753 2524
636aa200 2525static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
b61f2753 2526{
76db3ba4
AJ
2527 tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
2528 if (unlikely(ctx->le_mode)) {
66896cb8 2529 tcg_gen_bswap64_i64(arg1, arg1);
76db3ba4 2530 }
b61f2753
AJ
2531}
2532
636aa200 2533static inline void gen_qemu_st8(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2534{
76db3ba4 2535 tcg_gen_qemu_st8(arg1, arg2, ctx->mem_idx);
b61f2753
AJ
2536}
2537
636aa200 2538static inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2539{
76db3ba4 2540 if (unlikely(ctx->le_mode)) {
76db3ba4
AJ
2541 TCGv t0 = tcg_temp_new();
2542 tcg_gen_ext16u_tl(t0, arg1);
fa3966a3 2543 tcg_gen_bswap16_tl(t0, t0);
76db3ba4
AJ
2544 tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2545 tcg_temp_free(t0);
76db3ba4
AJ
2546 } else {
2547 tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2548 }
b61f2753
AJ
2549}
2550
636aa200 2551static inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2552{
76db3ba4 2553 if (unlikely(ctx->le_mode)) {
fa3966a3
AJ
2554 TCGv t0 = tcg_temp_new();
2555 tcg_gen_ext32u_tl(t0, arg1);
2556 tcg_gen_bswap32_tl(t0, t0);
76db3ba4
AJ
2557 tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2558 tcg_temp_free(t0);
76db3ba4
AJ
2559 } else {
2560 tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2561 }
b61f2753
AJ
2562}
2563
636aa200 2564static inline void gen_qemu_st64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
b61f2753 2565{
76db3ba4 2566 if (unlikely(ctx->le_mode)) {
a7812ae4 2567 TCGv_i64 t0 = tcg_temp_new_i64();
66896cb8 2568 tcg_gen_bswap64_i64(t0, arg1);
76db3ba4 2569 tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
a7812ae4 2570 tcg_temp_free_i64(t0);
b61f2753 2571 } else
76db3ba4 2572 tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
b61f2753
AJ
2573}
2574
0c8aacd4 2575#define GEN_LD(name, ldop, opc, type) \
99e300ef 2576static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 2577{ \
76db3ba4
AJ
2578 TCGv EA; \
2579 gen_set_access_type(ctx, ACCESS_INT); \
2580 EA = tcg_temp_new(); \
2581 gen_addr_imm_index(ctx, EA, 0); \
2582 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753 2583 tcg_temp_free(EA); \
79aceca5
FB
2584}
2585
0c8aacd4 2586#define GEN_LDU(name, ldop, opc, type) \
99e300ef 2587static void glue(gen_, name##u)(DisasContext *ctx) \
79aceca5 2588{ \
b61f2753 2589 TCGv EA; \
76a66253
JM
2590 if (unlikely(rA(ctx->opcode) == 0 || \
2591 rA(ctx->opcode) == rD(ctx->opcode))) { \
e06fcd75 2592 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2593 return; \
9a64fbe4 2594 } \
76db3ba4 2595 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2596 EA = tcg_temp_new(); \
9d53c753 2597 if (type == PPC_64B) \
76db3ba4 2598 gen_addr_imm_index(ctx, EA, 0x03); \
9d53c753 2599 else \
76db3ba4
AJ
2600 gen_addr_imm_index(ctx, EA, 0); \
2601 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753
AJ
2602 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2603 tcg_temp_free(EA); \
79aceca5
FB
2604}
2605
0c8aacd4 2606#define GEN_LDUX(name, ldop, opc2, opc3, type) \
99e300ef 2607static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 2608{ \
b61f2753 2609 TCGv EA; \
76a66253
JM
2610 if (unlikely(rA(ctx->opcode) == 0 || \
2611 rA(ctx->opcode) == rD(ctx->opcode))) { \
e06fcd75 2612 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2613 return; \
9a64fbe4 2614 } \
76db3ba4 2615 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2616 EA = tcg_temp_new(); \
76db3ba4
AJ
2617 gen_addr_reg_index(ctx, EA); \
2618 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753
AJ
2619 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2620 tcg_temp_free(EA); \
79aceca5
FB
2621}
2622
0c8aacd4 2623#define GEN_LDX(name, ldop, opc2, opc3, type) \
99e300ef 2624static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 2625{ \
76db3ba4
AJ
2626 TCGv EA; \
2627 gen_set_access_type(ctx, ACCESS_INT); \
2628 EA = tcg_temp_new(); \
2629 gen_addr_reg_index(ctx, EA); \
2630 gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
b61f2753 2631 tcg_temp_free(EA); \
79aceca5
FB
2632}
2633
0c8aacd4
AJ
2634#define GEN_LDS(name, ldop, op, type) \
2635GEN_LD(name, ldop, op | 0x20, type); \
2636GEN_LDU(name, ldop, op | 0x21, type); \
2637GEN_LDUX(name, ldop, 0x17, op | 0x01, type); \
2638GEN_LDX(name, ldop, 0x17, op | 0x00, type)
79aceca5
FB
2639
2640/* lbz lbzu lbzux lbzx */
0c8aacd4 2641GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
79aceca5 2642/* lha lhau lhaux lhax */
0c8aacd4 2643GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
79aceca5 2644/* lhz lhzu lhzux lhzx */
0c8aacd4 2645GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
79aceca5 2646/* lwz lwzu lwzux lwzx */
0c8aacd4 2647GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
d9bce9d9 2648#if defined(TARGET_PPC64)
d9bce9d9 2649/* lwaux */
0c8aacd4 2650GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
d9bce9d9 2651/* lwax */
0c8aacd4 2652GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
d9bce9d9 2653/* ldux */
0c8aacd4 2654GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
d9bce9d9 2655/* ldx */
0c8aacd4 2656GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
99e300ef
BS
2657
2658static void gen_ld(DisasContext *ctx)
d9bce9d9 2659{
b61f2753 2660 TCGv EA;
d9bce9d9
JM
2661 if (Rc(ctx->opcode)) {
2662 if (unlikely(rA(ctx->opcode) == 0 ||
2663 rA(ctx->opcode) == rD(ctx->opcode))) {
e06fcd75 2664 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
d9bce9d9
JM
2665 return;
2666 }
2667 }
76db3ba4 2668 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 2669 EA = tcg_temp_new();
76db3ba4 2670 gen_addr_imm_index(ctx, EA, 0x03);
d9bce9d9
JM
2671 if (ctx->opcode & 0x02) {
2672 /* lwa (lwau is undefined) */
76db3ba4 2673 gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
d9bce9d9
JM
2674 } else {
2675 /* ld - ldu */
76db3ba4 2676 gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
d9bce9d9 2677 }
d9bce9d9 2678 if (Rc(ctx->opcode))
b61f2753
AJ
2679 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2680 tcg_temp_free(EA);
d9bce9d9 2681}
99e300ef 2682
54623277 2683/* lq */
99e300ef 2684static void gen_lq(DisasContext *ctx)
be147d08
JM
2685{
2686#if defined(CONFIG_USER_ONLY)
e06fcd75 2687 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
2688#else
2689 int ra, rd;
b61f2753 2690 TCGv EA;
be147d08
JM
2691
2692 /* Restore CPU state */
76db3ba4 2693 if (unlikely(ctx->mem_idx == 0)) {
e06fcd75 2694 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
2695 return;
2696 }
2697 ra = rA(ctx->opcode);
2698 rd = rD(ctx->opcode);
2699 if (unlikely((rd & 1) || rd == ra)) {
e06fcd75 2700 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
be147d08
JM
2701 return;
2702 }
76db3ba4 2703 if (unlikely(ctx->le_mode)) {
be147d08 2704 /* Little-endian mode is not handled */
e06fcd75 2705 gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
be147d08
JM
2706 return;
2707 }
76db3ba4 2708 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 2709 EA = tcg_temp_new();
76db3ba4
AJ
2710 gen_addr_imm_index(ctx, EA, 0x0F);
2711 gen_qemu_ld64(ctx, cpu_gpr[rd], EA);
2712 gen_addr_add(ctx, EA, EA, 8);
2713 gen_qemu_ld64(ctx, cpu_gpr[rd+1], EA);
b61f2753 2714 tcg_temp_free(EA);
be147d08
JM
2715#endif
2716}
d9bce9d9 2717#endif
79aceca5
FB
2718
2719/*** Integer store ***/
0c8aacd4 2720#define GEN_ST(name, stop, opc, type) \
99e300ef 2721static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 2722{ \
76db3ba4
AJ
2723 TCGv EA; \
2724 gen_set_access_type(ctx, ACCESS_INT); \
2725 EA = tcg_temp_new(); \
2726 gen_addr_imm_index(ctx, EA, 0); \
2727 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753 2728 tcg_temp_free(EA); \
79aceca5
FB
2729}
2730
0c8aacd4 2731#define GEN_STU(name, stop, opc, type) \
99e300ef 2732static void glue(gen_, stop##u)(DisasContext *ctx) \
79aceca5 2733{ \
b61f2753 2734 TCGv EA; \
76a66253 2735 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 2736 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2737 return; \
9a64fbe4 2738 } \
76db3ba4 2739 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2740 EA = tcg_temp_new(); \
9d53c753 2741 if (type == PPC_64B) \
76db3ba4 2742 gen_addr_imm_index(ctx, EA, 0x03); \
9d53c753 2743 else \
76db3ba4
AJ
2744 gen_addr_imm_index(ctx, EA, 0); \
2745 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753
AJ
2746 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2747 tcg_temp_free(EA); \
79aceca5
FB
2748}
2749
0c8aacd4 2750#define GEN_STUX(name, stop, opc2, opc3, type) \
99e300ef 2751static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 2752{ \
b61f2753 2753 TCGv EA; \
76a66253 2754 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 2755 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 2756 return; \
9a64fbe4 2757 } \
76db3ba4 2758 gen_set_access_type(ctx, ACCESS_INT); \
0c8aacd4 2759 EA = tcg_temp_new(); \
76db3ba4
AJ
2760 gen_addr_reg_index(ctx, EA); \
2761 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753
AJ
2762 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2763 tcg_temp_free(EA); \
79aceca5
FB
2764}
2765
0c8aacd4 2766#define GEN_STX(name, stop, opc2, opc3, type) \
99e300ef 2767static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 2768{ \
76db3ba4
AJ
2769 TCGv EA; \
2770 gen_set_access_type(ctx, ACCESS_INT); \
2771 EA = tcg_temp_new(); \
2772 gen_addr_reg_index(ctx, EA); \
2773 gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
b61f2753 2774 tcg_temp_free(EA); \
79aceca5
FB
2775}
2776
0c8aacd4
AJ
2777#define GEN_STS(name, stop, op, type) \
2778GEN_ST(name, stop, op | 0x20, type); \
2779GEN_STU(name, stop, op | 0x21, type); \
2780GEN_STUX(name, stop, 0x17, op | 0x01, type); \
2781GEN_STX(name, stop, 0x17, op | 0x00, type)
79aceca5
FB
2782
2783/* stb stbu stbux stbx */
0c8aacd4 2784GEN_STS(stb, st8, 0x06, PPC_INTEGER);
79aceca5 2785/* sth sthu sthux sthx */
0c8aacd4 2786GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
79aceca5 2787/* stw stwu stwux stwx */
0c8aacd4 2788GEN_STS(stw, st32, 0x04, PPC_INTEGER);
d9bce9d9 2789#if defined(TARGET_PPC64)
0c8aacd4
AJ
2790GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
2791GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
99e300ef
BS
2792
2793static void gen_std(DisasContext *ctx)
d9bce9d9 2794{
be147d08 2795 int rs;
b61f2753 2796 TCGv EA;
be147d08
JM
2797
2798 rs = rS(ctx->opcode);
2799 if ((ctx->opcode & 0x3) == 0x2) {
2800#if defined(CONFIG_USER_ONLY)
e06fcd75 2801 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
2802#else
2803 /* stq */
76db3ba4 2804 if (unlikely(ctx->mem_idx == 0)) {
e06fcd75 2805 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
2806 return;
2807 }
2808 if (unlikely(rs & 1)) {
e06fcd75 2809 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
d9bce9d9
JM
2810 return;
2811 }
76db3ba4 2812 if (unlikely(ctx->le_mode)) {
be147d08 2813 /* Little-endian mode is not handled */
e06fcd75 2814 gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
be147d08
JM
2815 return;
2816 }
76db3ba4 2817 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 2818 EA = tcg_temp_new();
76db3ba4
AJ
2819 gen_addr_imm_index(ctx, EA, 0x03);
2820 gen_qemu_st64(ctx, cpu_gpr[rs], EA);
2821 gen_addr_add(ctx, EA, EA, 8);
2822 gen_qemu_st64(ctx, cpu_gpr[rs+1], EA);
b61f2753 2823 tcg_temp_free(EA);
be147d08
JM
2824#endif
2825 } else {
2826 /* std / stdu */
2827 if (Rc(ctx->opcode)) {
2828 if (unlikely(rA(ctx->opcode) == 0)) {
e06fcd75 2829 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
be147d08
JM
2830 return;
2831 }
2832 }
76db3ba4 2833 gen_set_access_type(ctx, ACCESS_INT);
a7812ae4 2834 EA = tcg_temp_new();
76db3ba4
AJ
2835 gen_addr_imm_index(ctx, EA, 0x03);
2836 gen_qemu_st64(ctx, cpu_gpr[rs], EA);
be147d08 2837 if (Rc(ctx->opcode))
b61f2753
AJ
2838 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2839 tcg_temp_free(EA);
d9bce9d9 2840 }
d9bce9d9
JM
2841}
2842#endif
79aceca5
FB
2843/*** Integer load and store with byte reverse ***/
2844/* lhbrx */
86178a57 2845static inline void gen_qemu_ld16ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2846{
76db3ba4
AJ
2847 tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
2848 if (likely(!ctx->le_mode)) {
fa3966a3 2849 tcg_gen_bswap16_tl(arg1, arg1);
76db3ba4 2850 }
b61f2753 2851}
0c8aacd4 2852GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
b61f2753 2853
79aceca5 2854/* lwbrx */
86178a57 2855static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2856{
76db3ba4
AJ
2857 tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
2858 if (likely(!ctx->le_mode)) {
fa3966a3 2859 tcg_gen_bswap32_tl(arg1, arg1);
76db3ba4 2860 }
b61f2753 2861}
0c8aacd4 2862GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
b61f2753 2863
79aceca5 2864/* sthbrx */
86178a57 2865static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2866{
76db3ba4 2867 if (likely(!ctx->le_mode)) {
76db3ba4
AJ
2868 TCGv t0 = tcg_temp_new();
2869 tcg_gen_ext16u_tl(t0, arg1);
fa3966a3 2870 tcg_gen_bswap16_tl(t0, t0);
76db3ba4
AJ
2871 tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
2872 tcg_temp_free(t0);
76db3ba4
AJ
2873 } else {
2874 tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
2875 }
b61f2753 2876}
0c8aacd4 2877GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
b61f2753 2878
79aceca5 2879/* stwbrx */
86178a57 2880static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
b61f2753 2881{
76db3ba4 2882 if (likely(!ctx->le_mode)) {
fa3966a3
AJ
2883 TCGv t0 = tcg_temp_new();
2884 tcg_gen_ext32u_tl(t0, arg1);
2885 tcg_gen_bswap32_tl(t0, t0);
76db3ba4
AJ
2886 tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
2887 tcg_temp_free(t0);
76db3ba4
AJ
2888 } else {
2889 tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
2890 }
b61f2753 2891}
0c8aacd4 2892GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
79aceca5
FB
2893
2894/*** Integer load and store multiple ***/
99e300ef 2895
54623277 2896/* lmw */
99e300ef 2897static void gen_lmw(DisasContext *ctx)
79aceca5 2898{
76db3ba4
AJ
2899 TCGv t0;
2900 TCGv_i32 t1;
2901 gen_set_access_type(ctx, ACCESS_INT);
76a66253 2902 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 2903 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
2904 t0 = tcg_temp_new();
2905 t1 = tcg_const_i32(rD(ctx->opcode));
2906 gen_addr_imm_index(ctx, t0, 0);
ff4a62cd
AJ
2907 gen_helper_lmw(t0, t1);
2908 tcg_temp_free(t0);
2909 tcg_temp_free_i32(t1);
79aceca5
FB
2910}
2911
2912/* stmw */
99e300ef 2913static void gen_stmw(DisasContext *ctx)
79aceca5 2914{
76db3ba4
AJ
2915 TCGv t0;
2916 TCGv_i32 t1;
2917 gen_set_access_type(ctx, ACCESS_INT);
76a66253 2918 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 2919 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
2920 t0 = tcg_temp_new();
2921 t1 = tcg_const_i32(rS(ctx->opcode));
2922 gen_addr_imm_index(ctx, t0, 0);
ff4a62cd
AJ
2923 gen_helper_stmw(t0, t1);
2924 tcg_temp_free(t0);
2925 tcg_temp_free_i32(t1);
79aceca5
FB
2926}
2927
2928/*** Integer load and store strings ***/
54623277 2929
79aceca5 2930/* lswi */
3fc6c082 2931/* PowerPC32 specification says we must generate an exception if
9a64fbe4
FB
2932 * rA is in the range of registers to be loaded.
2933 * In an other hand, IBM says this is valid, but rA won't be loaded.
2934 * For now, I'll follow the spec...
2935 */
99e300ef 2936static void gen_lswi(DisasContext *ctx)
79aceca5 2937{
dfbc799d
AJ
2938 TCGv t0;
2939 TCGv_i32 t1, t2;
79aceca5
FB
2940 int nb = NB(ctx->opcode);
2941 int start = rD(ctx->opcode);
9a64fbe4 2942 int ra = rA(ctx->opcode);
79aceca5
FB
2943 int nr;
2944
2945 if (nb == 0)
2946 nb = 32;
2947 nr = nb / 4;
76a66253
JM
2948 if (unlikely(((start + nr) > 32 &&
2949 start <= ra && (start + nr - 32) > ra) ||
2950 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
e06fcd75 2951 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
9fddaa0c 2952 return;
297d8e62 2953 }
76db3ba4 2954 gen_set_access_type(ctx, ACCESS_INT);
8dd4983c 2955 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 2956 gen_update_nip(ctx, ctx->nip - 4);
dfbc799d 2957 t0 = tcg_temp_new();
76db3ba4 2958 gen_addr_register(ctx, t0);
dfbc799d
AJ
2959 t1 = tcg_const_i32(nb);
2960 t2 = tcg_const_i32(start);
2961 gen_helper_lsw(t0, t1, t2);
2962 tcg_temp_free(t0);
2963 tcg_temp_free_i32(t1);
2964 tcg_temp_free_i32(t2);
79aceca5
FB
2965}
2966
2967/* lswx */
99e300ef 2968static void gen_lswx(DisasContext *ctx)
79aceca5 2969{
76db3ba4
AJ
2970 TCGv t0;
2971 TCGv_i32 t1, t2, t3;
2972 gen_set_access_type(ctx, ACCESS_INT);
76a66253 2973 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 2974 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
2975 t0 = tcg_temp_new();
2976 gen_addr_reg_index(ctx, t0);
2977 t1 = tcg_const_i32(rD(ctx->opcode));
2978 t2 = tcg_const_i32(rA(ctx->opcode));
2979 t3 = tcg_const_i32(rB(ctx->opcode));
dfbc799d
AJ
2980 gen_helper_lswx(t0, t1, t2, t3);
2981 tcg_temp_free(t0);
2982 tcg_temp_free_i32(t1);
2983 tcg_temp_free_i32(t2);
2984 tcg_temp_free_i32(t3);
79aceca5
FB
2985}
2986
2987/* stswi */
99e300ef 2988static void gen_stswi(DisasContext *ctx)
79aceca5 2989{
76db3ba4
AJ
2990 TCGv t0;
2991 TCGv_i32 t1, t2;
4b3686fa 2992 int nb = NB(ctx->opcode);
76db3ba4 2993 gen_set_access_type(ctx, ACCESS_INT);
76a66253 2994 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 2995 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
2996 t0 = tcg_temp_new();
2997 gen_addr_register(ctx, t0);
4b3686fa
FB
2998 if (nb == 0)
2999 nb = 32;
dfbc799d 3000 t1 = tcg_const_i32(nb);
76db3ba4 3001 t2 = tcg_const_i32(rS(ctx->opcode));
dfbc799d
AJ
3002 gen_helper_stsw(t0, t1, t2);
3003 tcg_temp_free(t0);
3004 tcg_temp_free_i32(t1);
3005 tcg_temp_free_i32(t2);
79aceca5
FB
3006}
3007
3008/* stswx */
99e300ef 3009static void gen_stswx(DisasContext *ctx)
79aceca5 3010{
76db3ba4
AJ
3011 TCGv t0;
3012 TCGv_i32 t1, t2;
3013 gen_set_access_type(ctx, ACCESS_INT);
8dd4983c 3014 /* NIP cannot be restored if the memory exception comes from an helper */
5fafdf24 3015 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
3016 t0 = tcg_temp_new();
3017 gen_addr_reg_index(ctx, t0);
3018 t1 = tcg_temp_new_i32();
dfbc799d
AJ
3019 tcg_gen_trunc_tl_i32(t1, cpu_xer);
3020 tcg_gen_andi_i32(t1, t1, 0x7F);
76db3ba4 3021 t2 = tcg_const_i32(rS(ctx->opcode));
dfbc799d
AJ
3022 gen_helper_stsw(t0, t1, t2);
3023 tcg_temp_free(t0);
3024 tcg_temp_free_i32(t1);
3025 tcg_temp_free_i32(t2);
79aceca5
FB
3026}
3027
3028/*** Memory synchronisation ***/
3029/* eieio */
99e300ef 3030static void gen_eieio(DisasContext *ctx)
79aceca5 3031{
79aceca5
FB
3032}
3033
3034/* isync */
99e300ef 3035static void gen_isync(DisasContext *ctx)
79aceca5 3036{
e06fcd75 3037 gen_stop_exception(ctx);
79aceca5
FB
3038}
3039
111bfab3 3040/* lwarx */
99e300ef 3041static void gen_lwarx(DisasContext *ctx)
79aceca5 3042{
76db3ba4 3043 TCGv t0;
18b21a2f 3044 TCGv gpr = cpu_gpr[rD(ctx->opcode)];
76db3ba4
AJ
3045 gen_set_access_type(ctx, ACCESS_RES);
3046 t0 = tcg_temp_local_new();
3047 gen_addr_reg_index(ctx, t0);
cf360a32 3048 gen_check_align(ctx, t0, 0x03);
18b21a2f 3049 gen_qemu_ld32u(ctx, gpr, t0);
cf360a32 3050 tcg_gen_mov_tl(cpu_reserve, t0);
18b21a2f 3051 tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
cf360a32 3052 tcg_temp_free(t0);
79aceca5
FB
3053}
3054
4425265b
NF
3055#if defined(CONFIG_USER_ONLY)
3056static void gen_conditional_store (DisasContext *ctx, TCGv EA,
3057 int reg, int size)
3058{
3059 TCGv t0 = tcg_temp_new();
3060 uint32_t save_exception = ctx->exception;
3061
3062 tcg_gen_st_tl(EA, cpu_env, offsetof(CPUState, reserve_ea));
3063 tcg_gen_movi_tl(t0, (size << 5) | reg);
3064 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, reserve_info));
3065 tcg_temp_free(t0);
3066 gen_update_nip(ctx, ctx->nip-4);
3067 ctx->exception = POWERPC_EXCP_BRANCH;
3068 gen_exception(ctx, POWERPC_EXCP_STCX);
3069 ctx->exception = save_exception;
3070}
3071#endif
3072
79aceca5 3073/* stwcx. */
e8eaa2c0 3074static void gen_stwcx_(DisasContext *ctx)
79aceca5 3075{
76db3ba4
AJ
3076 TCGv t0;
3077 gen_set_access_type(ctx, ACCESS_RES);
3078 t0 = tcg_temp_local_new();
3079 gen_addr_reg_index(ctx, t0);
cf360a32 3080 gen_check_align(ctx, t0, 0x03);
4425265b
NF
3081#if defined(CONFIG_USER_ONLY)
3082 gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
3083#else
3084 {
3085 int l1;
3086
3087 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3088 tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3089 tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3090 l1 = gen_new_label();
3091 tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3092 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3093 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3094 gen_set_label(l1);
3095 tcg_gen_movi_tl(cpu_reserve, -1);
3096 }
3097#endif
cf360a32 3098 tcg_temp_free(t0);
79aceca5
FB
3099}
3100
426613db 3101#if defined(TARGET_PPC64)
426613db 3102/* ldarx */
99e300ef 3103static void gen_ldarx(DisasContext *ctx)
426613db 3104{
76db3ba4 3105 TCGv t0;
18b21a2f 3106 TCGv gpr = cpu_gpr[rD(ctx->opcode)];
76db3ba4
AJ
3107 gen_set_access_type(ctx, ACCESS_RES);
3108 t0 = tcg_temp_local_new();
3109 gen_addr_reg_index(ctx, t0);
cf360a32 3110 gen_check_align(ctx, t0, 0x07);
18b21a2f 3111 gen_qemu_ld64(ctx, gpr, t0);
cf360a32 3112 tcg_gen_mov_tl(cpu_reserve, t0);
18b21a2f 3113 tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUState, reserve_val));
cf360a32 3114 tcg_temp_free(t0);
426613db
JM
3115}
3116
3117/* stdcx. */
e8eaa2c0 3118static void gen_stdcx_(DisasContext *ctx)
426613db 3119{
76db3ba4
AJ
3120 TCGv t0;
3121 gen_set_access_type(ctx, ACCESS_RES);
3122 t0 = tcg_temp_local_new();
3123 gen_addr_reg_index(ctx, t0);
cf360a32 3124 gen_check_align(ctx, t0, 0x07);
4425265b
NF
3125#if defined(CONFIG_USER_ONLY)
3126 gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
3127#else
3128 {
3129 int l1;
3130 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3131 tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3132 tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3133 l1 = gen_new_label();
3134 tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3135 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3136 gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
3137 gen_set_label(l1);
3138 tcg_gen_movi_tl(cpu_reserve, -1);
3139 }
3140#endif
cf360a32 3141 tcg_temp_free(t0);
426613db
JM
3142}
3143#endif /* defined(TARGET_PPC64) */
3144
79aceca5 3145/* sync */
99e300ef 3146static void gen_sync(DisasContext *ctx)
79aceca5 3147{
79aceca5
FB
3148}
3149
0db1b20e 3150/* wait */
99e300ef 3151static void gen_wait(DisasContext *ctx)
0db1b20e 3152{
931ff272
AJ
3153 TCGv_i32 t0 = tcg_temp_new_i32();
3154 tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
3155 tcg_temp_free_i32(t0);
0db1b20e 3156 /* Stop translation, as the CPU is supposed to sleep from now */
e06fcd75 3157 gen_exception_err(ctx, EXCP_HLT, 1);
0db1b20e
JM
3158}
3159
79aceca5 3160/*** Floating-point load ***/
a0d7d5a7 3161#define GEN_LDF(name, ldop, opc, type) \
99e300ef 3162static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 3163{ \
a0d7d5a7 3164 TCGv EA; \
76a66253 3165 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3166 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3167 return; \
3168 } \
76db3ba4 3169 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3170 EA = tcg_temp_new(); \
76db3ba4
AJ
3171 gen_addr_imm_index(ctx, EA, 0); \
3172 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7 3173 tcg_temp_free(EA); \
79aceca5
FB
3174}
3175
a0d7d5a7 3176#define GEN_LDUF(name, ldop, opc, type) \
99e300ef 3177static void glue(gen_, name##u)(DisasContext *ctx) \
79aceca5 3178{ \
a0d7d5a7 3179 TCGv EA; \
76a66253 3180 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3181 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3182 return; \
3183 } \
76a66253 3184 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3185 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3186 return; \
9a64fbe4 3187 } \
76db3ba4 3188 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3189 EA = tcg_temp_new(); \
76db3ba4
AJ
3190 gen_addr_imm_index(ctx, EA, 0); \
3191 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7
AJ
3192 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3193 tcg_temp_free(EA); \
79aceca5
FB
3194}
3195
a0d7d5a7 3196#define GEN_LDUXF(name, ldop, opc, type) \
99e300ef 3197static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 3198{ \
a0d7d5a7 3199 TCGv EA; \
76a66253 3200 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3201 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3202 return; \
3203 } \
76a66253 3204 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3205 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3206 return; \
9a64fbe4 3207 } \
76db3ba4 3208 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3209 EA = tcg_temp_new(); \
76db3ba4
AJ
3210 gen_addr_reg_index(ctx, EA); \
3211 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7
AJ
3212 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3213 tcg_temp_free(EA); \
79aceca5
FB
3214}
3215
a0d7d5a7 3216#define GEN_LDXF(name, ldop, opc2, opc3, type) \
99e300ef 3217static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 3218{ \
a0d7d5a7 3219 TCGv EA; \
76a66253 3220 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3221 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3222 return; \
3223 } \
76db3ba4 3224 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3225 EA = tcg_temp_new(); \
76db3ba4
AJ
3226 gen_addr_reg_index(ctx, EA); \
3227 gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA); \
a0d7d5a7 3228 tcg_temp_free(EA); \
79aceca5
FB
3229}
3230
a0d7d5a7
AJ
3231#define GEN_LDFS(name, ldop, op, type) \
3232GEN_LDF(name, ldop, op | 0x20, type); \
3233GEN_LDUF(name, ldop, op | 0x21, type); \
3234GEN_LDUXF(name, ldop, op | 0x01, type); \
3235GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3236
636aa200 3237static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
a0d7d5a7
AJ
3238{
3239 TCGv t0 = tcg_temp_new();
3240 TCGv_i32 t1 = tcg_temp_new_i32();
76db3ba4 3241 gen_qemu_ld32u(ctx, t0, arg2);
a0d7d5a7
AJ
3242 tcg_gen_trunc_tl_i32(t1, t0);
3243 tcg_temp_free(t0);
3244 gen_helper_float32_to_float64(arg1, t1);
3245 tcg_temp_free_i32(t1);
3246}
79aceca5 3247
a0d7d5a7
AJ
3248 /* lfd lfdu lfdux lfdx */
3249GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3250 /* lfs lfsu lfsux lfsx */
3251GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
79aceca5
FB
3252
3253/*** Floating-point store ***/
a0d7d5a7 3254#define GEN_STF(name, stop, opc, type) \
99e300ef 3255static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 3256{ \
a0d7d5a7 3257 TCGv EA; \
76a66253 3258 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3259 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3260 return; \
3261 } \
76db3ba4 3262 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3263 EA = tcg_temp_new(); \
76db3ba4
AJ
3264 gen_addr_imm_index(ctx, EA, 0); \
3265 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7 3266 tcg_temp_free(EA); \
79aceca5
FB
3267}
3268
a0d7d5a7 3269#define GEN_STUF(name, stop, opc, type) \
99e300ef 3270static void glue(gen_, name##u)(DisasContext *ctx) \
79aceca5 3271{ \
a0d7d5a7 3272 TCGv EA; \
76a66253 3273 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3274 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3275 return; \
3276 } \
76a66253 3277 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3278 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3279 return; \
9a64fbe4 3280 } \
76db3ba4 3281 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3282 EA = tcg_temp_new(); \
76db3ba4
AJ
3283 gen_addr_imm_index(ctx, EA, 0); \
3284 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7
AJ
3285 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3286 tcg_temp_free(EA); \
79aceca5
FB
3287}
3288
a0d7d5a7 3289#define GEN_STUXF(name, stop, opc, type) \
99e300ef 3290static void glue(gen_, name##ux)(DisasContext *ctx) \
79aceca5 3291{ \
a0d7d5a7 3292 TCGv EA; \
76a66253 3293 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3294 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3295 return; \
3296 } \
76a66253 3297 if (unlikely(rA(ctx->opcode) == 0)) { \
e06fcd75 3298 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
9fddaa0c 3299 return; \
9a64fbe4 3300 } \
76db3ba4 3301 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3302 EA = tcg_temp_new(); \
76db3ba4
AJ
3303 gen_addr_reg_index(ctx, EA); \
3304 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7
AJ
3305 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3306 tcg_temp_free(EA); \
79aceca5
FB
3307}
3308
a0d7d5a7 3309#define GEN_STXF(name, stop, opc2, opc3, type) \
99e300ef 3310static void glue(gen_, name##x)(DisasContext *ctx) \
79aceca5 3311{ \
a0d7d5a7 3312 TCGv EA; \
76a66253 3313 if (unlikely(!ctx->fpu_enabled)) { \
e06fcd75 3314 gen_exception(ctx, POWERPC_EXCP_FPU); \
4ecc3190
FB
3315 return; \
3316 } \
76db3ba4 3317 gen_set_access_type(ctx, ACCESS_FLOAT); \
a0d7d5a7 3318 EA = tcg_temp_new(); \
76db3ba4
AJ
3319 gen_addr_reg_index(ctx, EA); \
3320 gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA); \
a0d7d5a7 3321 tcg_temp_free(EA); \
79aceca5
FB
3322}
3323
a0d7d5a7
AJ
3324#define GEN_STFS(name, stop, op, type) \
3325GEN_STF(name, stop, op | 0x20, type); \
3326GEN_STUF(name, stop, op | 0x21, type); \
3327GEN_STUXF(name, stop, op | 0x01, type); \
3328GEN_STXF(name, stop, 0x17, op | 0x00, type)
3329
636aa200 3330static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
a0d7d5a7
AJ
3331{
3332 TCGv_i32 t0 = tcg_temp_new_i32();
3333 TCGv t1 = tcg_temp_new();
3334 gen_helper_float64_to_float32(t0, arg1);
3335 tcg_gen_extu_i32_tl(t1, t0);
3336 tcg_temp_free_i32(t0);
76db3ba4 3337 gen_qemu_st32(ctx, t1, arg2);
a0d7d5a7
AJ
3338 tcg_temp_free(t1);
3339}
79aceca5
FB
3340
3341/* stfd stfdu stfdux stfdx */
a0d7d5a7 3342GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
79aceca5 3343/* stfs stfsu stfsux stfsx */
a0d7d5a7 3344GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
79aceca5
FB
3345
3346/* Optional: */
636aa200 3347static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
a0d7d5a7
AJ
3348{
3349 TCGv t0 = tcg_temp_new();
3350 tcg_gen_trunc_i64_tl(t0, arg1),
76db3ba4 3351 gen_qemu_st32(ctx, t0, arg2);
a0d7d5a7
AJ
3352 tcg_temp_free(t0);
3353}
79aceca5 3354/* stfiwx */
a0d7d5a7 3355GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
79aceca5 3356
697ab892
DG
3357static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
3358{
3359#if defined(TARGET_PPC64)
3360 if (ctx->has_cfar)
3361 tcg_gen_movi_tl(cpu_cfar, nip);
3362#endif
3363}
3364
79aceca5 3365/*** Branch ***/
636aa200 3366static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c1942362
FB
3367{
3368 TranslationBlock *tb;
3369 tb = ctx->tb;
a2ffb812
AJ
3370#if defined(TARGET_PPC64)
3371 if (!ctx->sf_mode)
3372 dest = (uint32_t) dest;
3373#endif
57fec1fe 3374 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
8cbcb4fa 3375 likely(!ctx->singlestep_enabled)) {
57fec1fe 3376 tcg_gen_goto_tb(n);
a2ffb812 3377 tcg_gen_movi_tl(cpu_nip, dest & ~3);
4b4a72e5 3378 tcg_gen_exit_tb((tcg_target_long)tb + n);
c1942362 3379 } else {
a2ffb812 3380 tcg_gen_movi_tl(cpu_nip, dest & ~3);
8cbcb4fa
AJ
3381 if (unlikely(ctx->singlestep_enabled)) {
3382 if ((ctx->singlestep_enabled &
bdc4e053 3383 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
8cbcb4fa
AJ
3384 ctx->exception == POWERPC_EXCP_BRANCH) {
3385 target_ulong tmp = ctx->nip;
3386 ctx->nip = dest;
e06fcd75 3387 gen_exception(ctx, POWERPC_EXCP_TRACE);
8cbcb4fa
AJ
3388 ctx->nip = tmp;
3389 }
3390 if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
e06fcd75 3391 gen_debug_exception(ctx);
8cbcb4fa
AJ
3392 }
3393 }
57fec1fe 3394 tcg_gen_exit_tb(0);
c1942362 3395 }
c53be334
FB
3396}
3397
636aa200 3398static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
e1833e1f
JM
3399{
3400#if defined(TARGET_PPC64)
a2ffb812
AJ
3401 if (ctx->sf_mode == 0)
3402 tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
e1833e1f
JM
3403 else
3404#endif
a2ffb812 3405 tcg_gen_movi_tl(cpu_lr, nip);
e1833e1f
JM
3406}
3407
79aceca5 3408/* b ba bl bla */
99e300ef 3409static void gen_b(DisasContext *ctx)
79aceca5 3410{
76a66253 3411 target_ulong li, target;
38a64f9d 3412
8cbcb4fa 3413 ctx->exception = POWERPC_EXCP_BRANCH;
38a64f9d 3414 /* sign extend LI */
76a66253 3415#if defined(TARGET_PPC64)
d9bce9d9
JM
3416 if (ctx->sf_mode)
3417 li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3418 else
76a66253 3419#endif
d9bce9d9 3420 li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
76a66253 3421 if (likely(AA(ctx->opcode) == 0))
046d6672 3422 target = ctx->nip + li - 4;
79aceca5 3423 else
9a64fbe4 3424 target = li;
e1833e1f
JM
3425 if (LK(ctx->opcode))
3426 gen_setlr(ctx, ctx->nip);
697ab892 3427 gen_update_cfar(ctx, ctx->nip);
c1942362 3428 gen_goto_tb(ctx, 0, target);
79aceca5
FB
3429}
3430
e98a6e40
FB
3431#define BCOND_IM 0
3432#define BCOND_LR 1
3433#define BCOND_CTR 2
3434
636aa200 3435static inline void gen_bcond(DisasContext *ctx, int type)
d9bce9d9 3436{
d9bce9d9 3437 uint32_t bo = BO(ctx->opcode);
05f92404 3438 int l1;
a2ffb812 3439 TCGv target;
e98a6e40 3440
8cbcb4fa 3441 ctx->exception = POWERPC_EXCP_BRANCH;
a2ffb812 3442 if (type == BCOND_LR || type == BCOND_CTR) {
a7812ae4 3443 target = tcg_temp_local_new();
a2ffb812
AJ
3444 if (type == BCOND_CTR)
3445 tcg_gen_mov_tl(target, cpu_ctr);
3446 else
3447 tcg_gen_mov_tl(target, cpu_lr);
d2e9fd8f 3448 } else {
3449 TCGV_UNUSED(target);
e98a6e40 3450 }
e1833e1f
JM
3451 if (LK(ctx->opcode))
3452 gen_setlr(ctx, ctx->nip);
a2ffb812
AJ
3453 l1 = gen_new_label();
3454 if ((bo & 0x4) == 0) {
3455 /* Decrement and test CTR */
a7812ae4 3456 TCGv temp = tcg_temp_new();
a2ffb812 3457 if (unlikely(type == BCOND_CTR)) {
e06fcd75 3458 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
a2ffb812
AJ
3459 return;
3460 }
3461 tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
d9bce9d9 3462#if defined(TARGET_PPC64)
a2ffb812
AJ
3463 if (!ctx->sf_mode)
3464 tcg_gen_ext32u_tl(temp, cpu_ctr);
3465 else
d9bce9d9 3466#endif
a2ffb812
AJ
3467 tcg_gen_mov_tl(temp, cpu_ctr);
3468 if (bo & 0x2) {
3469 tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3470 } else {
3471 tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
e98a6e40 3472 }
a7812ae4 3473 tcg_temp_free(temp);
a2ffb812
AJ
3474 }
3475 if ((bo & 0x10) == 0) {
3476 /* Test CR */
3477 uint32_t bi = BI(ctx->opcode);
3478 uint32_t mask = 1 << (3 - (bi & 0x03));
a7812ae4 3479 TCGv_i32 temp = tcg_temp_new_i32();
a2ffb812 3480
d9bce9d9 3481 if (bo & 0x8) {
a2ffb812
AJ
3482 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3483 tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
d9bce9d9 3484 } else {
a2ffb812
AJ
3485 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3486 tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
d9bce9d9 3487 }
a7812ae4 3488 tcg_temp_free_i32(temp);
d9bce9d9 3489 }
697ab892 3490 gen_update_cfar(ctx, ctx->nip);
e98a6e40 3491 if (type == BCOND_IM) {
a2ffb812
AJ
3492 target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3493 if (likely(AA(ctx->opcode) == 0)) {
3494 gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3495 } else {
3496 gen_goto_tb(ctx, 0, li);
3497 }
c53be334 3498 gen_set_label(l1);
c1942362 3499 gen_goto_tb(ctx, 1, ctx->nip);
e98a6e40 3500 } else {
d9bce9d9 3501#if defined(TARGET_PPC64)
a2ffb812
AJ
3502 if (!(ctx->sf_mode))
3503 tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3504 else
3505#endif
3506 tcg_gen_andi_tl(cpu_nip, target, ~3);
3507 tcg_gen_exit_tb(0);
3508 gen_set_label(l1);
3509#if defined(TARGET_PPC64)
3510 if (!(ctx->sf_mode))
3511 tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
d9bce9d9
JM
3512 else
3513#endif
a2ffb812 3514 tcg_gen_movi_tl(cpu_nip, ctx->nip);
57fec1fe 3515 tcg_gen_exit_tb(0);
08e46e54 3516 }
e98a6e40
FB
3517}
3518
99e300ef 3519static void gen_bc(DisasContext *ctx)
3b46e624 3520{
e98a6e40
FB
3521 gen_bcond(ctx, BCOND_IM);
3522}
3523
99e300ef 3524static void gen_bcctr(DisasContext *ctx)
3b46e624 3525{
e98a6e40
FB
3526 gen_bcond(ctx, BCOND_CTR);
3527}
3528
99e300ef 3529static void gen_bclr(DisasContext *ctx)
3b46e624 3530{
e98a6e40
FB
3531 gen_bcond(ctx, BCOND_LR);
3532}
79aceca5
FB
3533
3534/*** Condition register logical ***/
e1571908 3535#define GEN_CRLOGIC(name, tcg_op, opc) \
99e300ef 3536static void glue(gen_, name)(DisasContext *ctx) \
79aceca5 3537{ \
fc0d441e
JM
3538 uint8_t bitmask; \
3539 int sh; \
a7812ae4 3540 TCGv_i32 t0, t1; \
fc0d441e 3541 sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
a7812ae4 3542 t0 = tcg_temp_new_i32(); \
fc0d441e 3543 if (sh > 0) \
fea0c503 3544 tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \
fc0d441e 3545 else if (sh < 0) \
fea0c503 3546 tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \
e1571908 3547 else \
fea0c503 3548 tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \
a7812ae4 3549 t1 = tcg_temp_new_i32(); \
fc0d441e
JM
3550 sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
3551 if (sh > 0) \
fea0c503 3552 tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \
fc0d441e 3553 else if (sh < 0) \
fea0c503 3554 tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \
e1571908 3555 else \
fea0c503
AJ
3556 tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \
3557 tcg_op(t0, t0, t1); \
fc0d441e 3558 bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
fea0c503
AJ
3559 tcg_gen_andi_i32(t0, t0, bitmask); \
3560 tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
3561 tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \
a7812ae4
PB
3562 tcg_temp_free_i32(t0); \
3563 tcg_temp_free_i32(t1); \
79aceca5
FB
3564}
3565
3566/* crand */
e1571908 3567GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
79aceca5 3568/* crandc */
e1571908 3569GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
79aceca5 3570/* creqv */
e1571908 3571GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
79aceca5 3572/* crnand */
e1571908 3573GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
79aceca5 3574/* crnor */
e1571908 3575GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
79aceca5 3576/* cror */
e1571908 3577GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
79aceca5 3578/* crorc */
e1571908 3579GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
79aceca5 3580/* crxor */
e1571908 3581GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
99e300ef 3582
54623277 3583/* mcrf */
99e300ef 3584static void gen_mcrf(DisasContext *ctx)
79aceca5 3585{
47e4661c 3586 tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
79aceca5
FB
3587}
3588
3589/*** System linkage ***/
99e300ef 3590
54623277 3591/* rfi (mem_idx only) */
99e300ef 3592static void gen_rfi(DisasContext *ctx)
79aceca5 3593{
9a64fbe4 3594#if defined(CONFIG_USER_ONLY)
e06fcd75 3595 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9a64fbe4
FB
3596#else
3597 /* Restore CPU state */
76db3ba4 3598 if (unlikely(!ctx->mem_idx)) {
e06fcd75 3599 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 3600 return;
9a64fbe4 3601 }
697ab892 3602 gen_update_cfar(ctx, ctx->nip);
d72a19f7 3603 gen_helper_rfi();
e06fcd75 3604 gen_sync_exception(ctx);
9a64fbe4 3605#endif
79aceca5
FB
3606}
3607
426613db 3608#if defined(TARGET_PPC64)
99e300ef 3609static void gen_rfid(DisasContext *ctx)
426613db
JM
3610{
3611#if defined(CONFIG_USER_ONLY)
e06fcd75 3612 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db
JM
3613#else
3614 /* Restore CPU state */
76db3ba4 3615 if (unlikely(!ctx->mem_idx)) {
e06fcd75 3616 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db
JM
3617 return;
3618 }
697ab892 3619 gen_update_cfar(ctx, ctx->nip);
d72a19f7 3620 gen_helper_rfid();
e06fcd75 3621 gen_sync_exception(ctx);
426613db
JM
3622#endif
3623}
426613db 3624
99e300ef 3625static void gen_hrfid(DisasContext *ctx)
be147d08
JM
3626{
3627#if defined(CONFIG_USER_ONLY)
e06fcd75 3628 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
3629#else
3630 /* Restore CPU state */
76db3ba4 3631 if (unlikely(ctx->mem_idx <= 1)) {
e06fcd75 3632 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
be147d08
JM
3633 return;
3634 }
d72a19f7 3635 gen_helper_hrfid();
e06fcd75 3636 gen_sync_exception(ctx);
be147d08
JM
3637#endif
3638}
3639#endif
3640
79aceca5 3641/* sc */
417bf010
JM
3642#if defined(CONFIG_USER_ONLY)
3643#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3644#else
3645#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3646#endif
99e300ef 3647static void gen_sc(DisasContext *ctx)
79aceca5 3648{
e1833e1f
JM
3649 uint32_t lev;
3650
3651 lev = (ctx->opcode >> 5) & 0x7F;
e06fcd75 3652 gen_exception_err(ctx, POWERPC_SYSCALL, lev);
79aceca5
FB
3653}
3654
3655/*** Trap ***/
99e300ef 3656
54623277 3657/* tw */
99e300ef 3658static void gen_tw(DisasContext *ctx)
79aceca5 3659{
cab3bee2 3660 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
3661 /* Update the nip since this might generate a trap exception */
3662 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3663 gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3664 tcg_temp_free_i32(t0);
79aceca5
FB
3665}
3666
3667/* twi */
99e300ef 3668static void gen_twi(DisasContext *ctx)
79aceca5 3669{
cab3bee2
AJ
3670 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3671 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
3672 /* Update the nip since this might generate a trap exception */
3673 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3674 gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
3675 tcg_temp_free(t0);
3676 tcg_temp_free_i32(t1);
79aceca5
FB
3677}
3678
d9bce9d9
JM
3679#if defined(TARGET_PPC64)
3680/* td */
99e300ef 3681static void gen_td(DisasContext *ctx)
d9bce9d9 3682{
cab3bee2 3683 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
3684 /* Update the nip since this might generate a trap exception */
3685 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3686 gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3687 tcg_temp_free_i32(t0);
d9bce9d9
JM
3688}
3689
3690/* tdi */
99e300ef 3691static void gen_tdi(DisasContext *ctx)
d9bce9d9 3692{
cab3bee2
AJ
3693 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3694 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
db9a231d
AJ
3695 /* Update the nip since this might generate a trap exception */
3696 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3697 gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
3698 tcg_temp_free(t0);
3699 tcg_temp_free_i32(t1);
d9bce9d9
JM
3700}
3701#endif
3702
79aceca5 3703/*** Processor control ***/
99e300ef 3704
54623277 3705/* mcrxr */
99e300ef 3706static void gen_mcrxr(DisasContext *ctx)
79aceca5 3707{
3d7b417e
AJ
3708 tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
3709 tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
269f3e95 3710 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
79aceca5
FB
3711}
3712
0cfe11ea 3713/* mfcr mfocrf */
99e300ef 3714static void gen_mfcr(DisasContext *ctx)
79aceca5 3715{
76a66253 3716 uint32_t crm, crn;
3b46e624 3717
76a66253
JM
3718 if (likely(ctx->opcode & 0x00100000)) {
3719 crm = CRM(ctx->opcode);
8dd640e4 3720 if (likely(crm && ((crm & (crm - 1)) == 0))) {
0cfe11ea 3721 crn = ctz32 (crm);
e1571908 3722 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
0497d2f4
AJ
3723 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
3724 cpu_gpr[rD(ctx->opcode)], crn * 4);
76a66253 3725 }
d9bce9d9 3726 } else {
651721b2
AJ
3727 TCGv_i32 t0 = tcg_temp_new_i32();
3728 tcg_gen_mov_i32(t0, cpu_crf[0]);
3729 tcg_gen_shli_i32(t0, t0, 4);
3730 tcg_gen_or_i32(t0, t0, cpu_crf[1]);
3731 tcg_gen_shli_i32(t0, t0, 4);
3732 tcg_gen_or_i32(t0, t0, cpu_crf[2]);
3733 tcg_gen_shli_i32(t0, t0, 4);
3734 tcg_gen_or_i32(t0, t0, cpu_crf[3]);
3735 tcg_gen_shli_i32(t0, t0, 4);
3736 tcg_gen_or_i32(t0, t0, cpu_crf[4]);
3737 tcg_gen_shli_i32(t0, t0, 4);
3738 tcg_gen_or_i32(t0, t0, cpu_crf[5]);
3739 tcg_gen_shli_i32(t0, t0, 4);
3740 tcg_gen_or_i32(t0, t0, cpu_crf[6]);
3741 tcg_gen_shli_i32(t0, t0, 4);
3742 tcg_gen_or_i32(t0, t0, cpu_crf[7]);
3743 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
3744 tcg_temp_free_i32(t0);
d9bce9d9 3745 }
79aceca5
FB
3746}
3747
3748/* mfmsr */
99e300ef 3749static void gen_mfmsr(DisasContext *ctx)
79aceca5 3750{
9a64fbe4 3751#if defined(CONFIG_USER_ONLY)
e06fcd75 3752 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 3753#else
76db3ba4 3754 if (unlikely(!ctx->mem_idx)) {
e06fcd75 3755 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 3756 return;
9a64fbe4 3757 }
6527f6ea 3758 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
9a64fbe4 3759#endif
79aceca5
FB
3760}
3761
7b13448f 3762static void spr_noaccess(void *opaque, int gprn, int sprn)
3fc6c082 3763{
7b13448f 3764#if 0
3fc6c082
FB
3765 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3766 printf("ERROR: try to access SPR %d !\n", sprn);
7b13448f 3767#endif
3fc6c082
FB
3768}
3769#define SPR_NOACCESS (&spr_noaccess)
3fc6c082 3770
79aceca5 3771/* mfspr */
636aa200 3772static inline void gen_op_mfspr(DisasContext *ctx)
79aceca5 3773{
45d827d2 3774 void (*read_cb)(void *opaque, int gprn, int sprn);
79aceca5
FB
3775 uint32_t sprn = SPR(ctx->opcode);
3776
3fc6c082 3777#if !defined(CONFIG_USER_ONLY)
76db3ba4 3778 if (ctx->mem_idx == 2)
be147d08 3779 read_cb = ctx->spr_cb[sprn].hea_read;
76db3ba4 3780 else if (ctx->mem_idx)
3fc6c082
FB
3781 read_cb = ctx->spr_cb[sprn].oea_read;
3782 else
9a64fbe4 3783#endif
3fc6c082 3784 read_cb = ctx->spr_cb[sprn].uea_read;
76a66253
JM
3785 if (likely(read_cb != NULL)) {
3786 if (likely(read_cb != SPR_NOACCESS)) {
45d827d2 3787 (*read_cb)(ctx, rD(ctx->opcode), sprn);
3fc6c082
FB
3788 } else {
3789 /* Privilege exception */
9fceefa7
JM
3790 /* This is a hack to avoid warnings when running Linux:
3791 * this OS breaks the PowerPC virtualisation model,
3792 * allowing userland application to read the PVR
3793 */
3794 if (sprn != SPR_PVR) {
93fcfe39 3795 qemu_log("Trying to read privileged spr %d %03x at "
90e189ec
BS
3796 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3797 printf("Trying to read privileged spr %d %03x at "
3798 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
f24e5695 3799 }
e06fcd75 3800 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
79aceca5 3801 }
3fc6c082
FB
3802 } else {
3803 /* Not defined */
93fcfe39 3804 qemu_log("Trying to read invalid spr %d %03x at "
90e189ec
BS
3805 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3806 printf("Trying to read invalid spr %d %03x at " TARGET_FMT_lx "\n",
077fc206 3807 sprn, sprn, ctx->nip);
e06fcd75 3808 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
79aceca5 3809 }
79aceca5
FB
3810}
3811
99e300ef 3812static void gen_mfspr(DisasContext *ctx)
79aceca5 3813{
3fc6c082 3814 gen_op_mfspr(ctx);
76a66253 3815}
3fc6c082
FB
3816
3817/* mftb */
99e300ef 3818static void gen_mftb(DisasContext *ctx)
3fc6c082
FB
3819{
3820 gen_op_mfspr(ctx);
79aceca5
FB
3821}
3822
0cfe11ea 3823/* mtcrf mtocrf*/
99e300ef 3824static void gen_mtcrf(DisasContext *ctx)
79aceca5 3825{
76a66253 3826 uint32_t crm, crn;
3b46e624 3827
76a66253 3828 crm = CRM(ctx->opcode);
8dd640e4 3829 if (likely((ctx->opcode & 0x00100000))) {
3830 if (crm && ((crm & (crm - 1)) == 0)) {
3831 TCGv_i32 temp = tcg_temp_new_i32();
0cfe11ea 3832 crn = ctz32 (crm);
8dd640e4 3833 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
0cfe11ea
AJ
3834 tcg_gen_shri_i32(temp, temp, crn * 4);
3835 tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
8dd640e4 3836 tcg_temp_free_i32(temp);
3837 }
76a66253 3838 } else {
651721b2
AJ
3839 TCGv_i32 temp = tcg_temp_new_i32();
3840 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3841 for (crn = 0 ; crn < 8 ; crn++) {
3842 if (crm & (1 << crn)) {
3843 tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
3844 tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
3845 }
3846 }
a7812ae4 3847 tcg_temp_free_i32(temp);
76a66253 3848 }
79aceca5
FB
3849}
3850
3851/* mtmsr */
426613db 3852#if defined(TARGET_PPC64)
99e300ef 3853static void gen_mtmsrd(DisasContext *ctx)
426613db
JM
3854{
3855#if defined(CONFIG_USER_ONLY)
e06fcd75 3856 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
426613db 3857#else
76db3ba4 3858 if (unlikely(!ctx->mem_idx)) {
e06fcd75 3859 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
426613db
JM
3860 return;
3861 }
be147d08
JM
3862 if (ctx->opcode & 0x00010000) {
3863 /* Special form that does not need any synchronisation */
6527f6ea
AJ
3864 TCGv t0 = tcg_temp_new();
3865 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3866 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3867 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3868 tcg_temp_free(t0);
be147d08 3869 } else {
056b05f8
JM
3870 /* XXX: we need to update nip before the store
3871 * if we enter power saving mode, we will exit the loop
3872 * directly from ppc_store_msr
3873 */
be147d08 3874 gen_update_nip(ctx, ctx->nip);
6527f6ea 3875 gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
be147d08
JM
3876 /* Must stop the translation as machine state (may have) changed */
3877 /* Note that mtmsr is not always defined as context-synchronizing */
e06fcd75 3878 gen_stop_exception(ctx);
be147d08 3879 }
426613db
JM
3880#endif
3881}
3882#endif
3883
99e300ef 3884static void gen_mtmsr(DisasContext *ctx)
79aceca5 3885{
9a64fbe4 3886#if defined(CONFIG_USER_ONLY)
e06fcd75 3887 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 3888#else
76db3ba4 3889 if (unlikely(!ctx->mem_idx)) {
e06fcd75 3890 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 3891 return;
9a64fbe4 3892 }
be147d08
JM
3893 if (ctx->opcode & 0x00010000) {
3894 /* Special form that does not need any synchronisation */
6527f6ea
AJ
3895 TCGv t0 = tcg_temp_new();
3896 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3897 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3898 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3899 tcg_temp_free(t0);
be147d08 3900 } else {
8018dc63
AG
3901 TCGv msr = tcg_temp_new();
3902
056b05f8
JM
3903 /* XXX: we need to update nip before the store
3904 * if we enter power saving mode, we will exit the loop
3905 * directly from ppc_store_msr
3906 */
be147d08 3907 gen_update_nip(ctx, ctx->nip);
d9bce9d9 3908#if defined(TARGET_PPC64)
8018dc63
AG
3909 tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
3910#else
3911 tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
d9bce9d9 3912#endif
8018dc63 3913 gen_helper_store_msr(msr);
be147d08 3914 /* Must stop the translation as machine state (may have) changed */
6527f6ea 3915 /* Note that mtmsr is not always defined as context-synchronizing */
e06fcd75 3916 gen_stop_exception(ctx);
be147d08 3917 }
9a64fbe4 3918#endif
79aceca5
FB
3919}
3920
3921/* mtspr */
99e300ef 3922static void gen_mtspr(DisasContext *ctx)
79aceca5 3923{
45d827d2 3924 void (*write_cb)(void *opaque, int sprn, int gprn);
79aceca5
FB
3925 uint32_t sprn = SPR(ctx->opcode);
3926
3fc6c082 3927#if !defined(CONFIG_USER_ONLY)
76db3ba4 3928 if (ctx->mem_idx == 2)
be147d08 3929 write_cb = ctx->spr_cb[sprn].hea_write;
76db3ba4 3930 else if (ctx->mem_idx)
3fc6c082
FB
3931 write_cb = ctx->spr_cb[sprn].oea_write;
3932 else
9a64fbe4 3933#endif
3fc6c082 3934 write_cb = ctx->spr_cb[sprn].uea_write;
76a66253
JM
3935 if (likely(write_cb != NULL)) {
3936 if (likely(write_cb != SPR_NOACCESS)) {
45d827d2 3937 (*write_cb)(ctx, sprn, rS(ctx->opcode));
3fc6c082
FB
3938 } else {
3939 /* Privilege exception */
93fcfe39 3940 qemu_log("Trying to write privileged spr %d %03x at "
90e189ec
BS
3941 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3942 printf("Trying to write privileged spr %d %03x at " TARGET_FMT_lx
3943 "\n", sprn, sprn, ctx->nip);
e06fcd75 3944 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253 3945 }
3fc6c082
FB
3946 } else {
3947 /* Not defined */
93fcfe39 3948 qemu_log("Trying to write invalid spr %d %03x at "
90e189ec
BS
3949 TARGET_FMT_lx "\n", sprn, sprn, ctx->nip);
3950 printf("Trying to write invalid spr %d %03x at " TARGET_FMT_lx "\n",
077fc206 3951 sprn, sprn, ctx->nip);
e06fcd75 3952 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
79aceca5 3953 }
79aceca5
FB
3954}
3955
3956/*** Cache management ***/
99e300ef 3957
54623277 3958/* dcbf */
99e300ef 3959static void gen_dcbf(DisasContext *ctx)
79aceca5 3960{
dac454af 3961 /* XXX: specification says this is treated as a load by the MMU */
76db3ba4
AJ
3962 TCGv t0;
3963 gen_set_access_type(ctx, ACCESS_CACHE);
3964 t0 = tcg_temp_new();
3965 gen_addr_reg_index(ctx, t0);
3966 gen_qemu_ld8u(ctx, t0, t0);
fea0c503 3967 tcg_temp_free(t0);
79aceca5
FB
3968}
3969
3970/* dcbi (Supervisor only) */
99e300ef 3971static void gen_dcbi(DisasContext *ctx)
79aceca5 3972{
a541f297 3973#if defined(CONFIG_USER_ONLY)
e06fcd75 3974 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a541f297 3975#else
b61f2753 3976 TCGv EA, val;
76db3ba4 3977 if (unlikely(!ctx->mem_idx)) {
e06fcd75 3978 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 3979 return;
9a64fbe4 3980 }
a7812ae4 3981 EA = tcg_temp_new();
76db3ba4
AJ
3982 gen_set_access_type(ctx, ACCESS_CACHE);
3983 gen_addr_reg_index(ctx, EA);
a7812ae4 3984 val = tcg_temp_new();
76a66253 3985 /* XXX: specification says this should be treated as a store by the MMU */
76db3ba4
AJ
3986 gen_qemu_ld8u(ctx, val, EA);
3987 gen_qemu_st8(ctx, val, EA);
b61f2753
AJ
3988 tcg_temp_free(val);
3989 tcg_temp_free(EA);
a541f297 3990#endif
79aceca5
FB
3991}
3992
3993/* dcdst */
99e300ef 3994static void gen_dcbst(DisasContext *ctx)
79aceca5 3995{
76a66253 3996 /* XXX: specification say this is treated as a load by the MMU */
76db3ba4
AJ
3997 TCGv t0;
3998 gen_set_access_type(ctx, ACCESS_CACHE);
3999 t0 = tcg_temp_new();
4000 gen_addr_reg_index(ctx, t0);
4001 gen_qemu_ld8u(ctx, t0, t0);
fea0c503 4002 tcg_temp_free(t0);
79aceca5
FB
4003}
4004
4005/* dcbt */
99e300ef 4006static void gen_dcbt(DisasContext *ctx)
79aceca5 4007{
0db1b20e 4008 /* interpreted as no-op */
76a66253
JM
4009 /* XXX: specification say this is treated as a load by the MMU
4010 * but does not generate any exception
4011 */
79aceca5
FB
4012}
4013
4014/* dcbtst */
99e300ef 4015static void gen_dcbtst(DisasContext *ctx)
79aceca5 4016{
0db1b20e 4017 /* interpreted as no-op */
76a66253
JM
4018 /* XXX: specification say this is treated as a load by the MMU
4019 * but does not generate any exception
4020 */
79aceca5
FB
4021}
4022
4023/* dcbz */
99e300ef 4024static void gen_dcbz(DisasContext *ctx)
79aceca5 4025{
76db3ba4
AJ
4026 TCGv t0;
4027 gen_set_access_type(ctx, ACCESS_CACHE);
799a8c8d
AJ
4028 /* NIP cannot be restored if the memory exception comes from an helper */
4029 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
4030 t0 = tcg_temp_new();
4031 gen_addr_reg_index(ctx, t0);
799a8c8d
AJ
4032 gen_helper_dcbz(t0);
4033 tcg_temp_free(t0);
d63001d1
JM
4034}
4035
e8eaa2c0 4036static void gen_dcbz_970(DisasContext *ctx)
d63001d1 4037{
76db3ba4
AJ
4038 TCGv t0;
4039 gen_set_access_type(ctx, ACCESS_CACHE);
799a8c8d
AJ
4040 /* NIP cannot be restored if the memory exception comes from an helper */
4041 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
4042 t0 = tcg_temp_new();
4043 gen_addr_reg_index(ctx, t0);
d63001d1 4044 if (ctx->opcode & 0x00200000)
799a8c8d 4045 gen_helper_dcbz(t0);
d63001d1 4046 else
799a8c8d
AJ
4047 gen_helper_dcbz_970(t0);
4048 tcg_temp_free(t0);
79aceca5
FB
4049}
4050
ae1c1a3d 4051/* dst / dstt */
99e300ef 4052static void gen_dst(DisasContext *ctx)
ae1c1a3d
AJ
4053{
4054 if (rA(ctx->opcode) == 0) {
4055 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4056 } else {
4057 /* interpreted as no-op */
4058 }
4059}
4060
4061/* dstst /dststt */
99e300ef 4062static void gen_dstst(DisasContext *ctx)
ae1c1a3d
AJ
4063{
4064 if (rA(ctx->opcode) == 0) {
4065 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
4066 } else {
4067 /* interpreted as no-op */
4068 }
4069
4070}
4071
4072/* dss / dssall */
99e300ef 4073static void gen_dss(DisasContext *ctx)
ae1c1a3d
AJ
4074{
4075 /* interpreted as no-op */
4076}
4077
79aceca5 4078/* icbi */
99e300ef 4079static void gen_icbi(DisasContext *ctx)
79aceca5 4080{
76db3ba4
AJ
4081 TCGv t0;
4082 gen_set_access_type(ctx, ACCESS_CACHE);
30032c94
JM
4083 /* NIP cannot be restored if the memory exception comes from an helper */
4084 gen_update_nip(ctx, ctx->nip - 4);
76db3ba4
AJ
4085 t0 = tcg_temp_new();
4086 gen_addr_reg_index(ctx, t0);
37d269df
AJ
4087 gen_helper_icbi(t0);
4088 tcg_temp_free(t0);
79aceca5
FB
4089}
4090
4091/* Optional: */
4092/* dcba */
99e300ef 4093static void gen_dcba(DisasContext *ctx)
79aceca5 4094{
0db1b20e
JM
4095 /* interpreted as no-op */
4096 /* XXX: specification say this is treated as a store by the MMU
4097 * but does not generate any exception
4098 */
79aceca5
FB
4099}
4100
4101/*** Segment register manipulation ***/
4102/* Supervisor only: */
99e300ef 4103
54623277 4104/* mfsr */
99e300ef 4105static void gen_mfsr(DisasContext *ctx)
79aceca5 4106{
9a64fbe4 4107#if defined(CONFIG_USER_ONLY)
e06fcd75 4108 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 4109#else
74d37793 4110 TCGv t0;
76db3ba4 4111 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4112 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 4113 return;
9a64fbe4 4114 }
74d37793
AJ
4115 t0 = tcg_const_tl(SR(ctx->opcode));
4116 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4117 tcg_temp_free(t0);
9a64fbe4 4118#endif
79aceca5
FB
4119}
4120
4121/* mfsrin */
99e300ef 4122static void gen_mfsrin(DisasContext *ctx)
79aceca5 4123{
9a64fbe4 4124#if defined(CONFIG_USER_ONLY)
e06fcd75 4125 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 4126#else
74d37793 4127 TCGv t0;
76db3ba4 4128 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4129 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 4130 return;
9a64fbe4 4131 }
74d37793
AJ
4132 t0 = tcg_temp_new();
4133 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4134 tcg_gen_andi_tl(t0, t0, 0xF);
4135 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
4136 tcg_temp_free(t0);
9a64fbe4 4137#endif
79aceca5
FB
4138}
4139
4140/* mtsr */
99e300ef 4141static void gen_mtsr(DisasContext *ctx)
79aceca5 4142{
9a64fbe4 4143#if defined(CONFIG_USER_ONLY)
e06fcd75 4144 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 4145#else
74d37793 4146 TCGv t0;
76db3ba4 4147 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4148 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 4149 return;
9a64fbe4 4150 }
74d37793
AJ
4151 t0 = tcg_const_tl(SR(ctx->opcode));
4152 gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
4153 tcg_temp_free(t0);
9a64fbe4 4154#endif
79aceca5
FB
4155}
4156
4157/* mtsrin */
99e300ef 4158static void gen_mtsrin(DisasContext *ctx)
79aceca5 4159{
9a64fbe4 4160#if defined(CONFIG_USER_ONLY)
e06fcd75 4161 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9a64fbe4 4162#else
74d37793 4163 TCGv t0;
76db3ba4 4164 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4165 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
9fddaa0c 4166 return;
9a64fbe4 4167 }
74d37793
AJ
4168 t0 = tcg_temp_new();
4169 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4170 tcg_gen_andi_tl(t0, t0, 0xF);
4171 gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]);
4172 tcg_temp_free(t0);
9a64fbe4 4173#endif
79aceca5
FB
4174}
4175
12de9a39
JM
4176#if defined(TARGET_PPC64)
4177/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
e8eaa2c0 4178
54623277 4179/* mfsr */
e8eaa2c0 4180static void gen_mfsr_64b(DisasContext *ctx)
12de9a39
JM
4181{
4182#if defined(CONFIG_USER_ONLY)
e06fcd75 4183 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39 4184#else
74d37793 4185 TCGv t0;
76db3ba4 4186 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4187 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39
JM
4188 return;
4189 }
74d37793 4190 t0 = tcg_const_tl(SR(ctx->opcode));
f6b868fc 4191 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
74d37793 4192 tcg_temp_free(t0);
12de9a39
JM
4193#endif
4194}
4195
4196/* mfsrin */
e8eaa2c0 4197static void gen_mfsrin_64b(DisasContext *ctx)
12de9a39
JM
4198{
4199#if defined(CONFIG_USER_ONLY)
e06fcd75 4200 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39 4201#else
74d37793 4202 TCGv t0;
76db3ba4 4203 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4204 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39
JM
4205 return;
4206 }
74d37793
AJ
4207 t0 = tcg_temp_new();
4208 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4209 tcg_gen_andi_tl(t0, t0, 0xF);
f6b868fc 4210 gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
74d37793 4211 tcg_temp_free(t0);
12de9a39
JM
4212#endif
4213}
4214
4215/* mtsr */
e8eaa2c0 4216static void gen_mtsr_64b(DisasContext *ctx)
12de9a39
JM
4217{
4218#if defined(CONFIG_USER_ONLY)
e06fcd75 4219 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39 4220#else
74d37793 4221 TCGv t0;
76db3ba4 4222 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4223 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39
JM
4224 return;
4225 }
74d37793 4226 t0 = tcg_const_tl(SR(ctx->opcode));
f6b868fc 4227 gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 4228 tcg_temp_free(t0);
12de9a39
JM
4229#endif
4230}
4231
4232/* mtsrin */
e8eaa2c0 4233static void gen_mtsrin_64b(DisasContext *ctx)
12de9a39
JM
4234{
4235#if defined(CONFIG_USER_ONLY)
e06fcd75 4236 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39 4237#else
74d37793 4238 TCGv t0;
76db3ba4 4239 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4240 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
12de9a39
JM
4241 return;
4242 }
74d37793
AJ
4243 t0 = tcg_temp_new();
4244 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
4245 tcg_gen_andi_tl(t0, t0, 0xF);
f6b868fc 4246 gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
74d37793 4247 tcg_temp_free(t0);
12de9a39
JM
4248#endif
4249}
f6b868fc
BS
4250
4251/* slbmte */
e8eaa2c0 4252static void gen_slbmte(DisasContext *ctx)
f6b868fc
BS
4253{
4254#if defined(CONFIG_USER_ONLY)
4255 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4256#else
4257 if (unlikely(!ctx->mem_idx)) {
4258 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4259 return;
4260 }
4261 gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
4262#endif
4263}
4264
efdef95f
DG
4265static void gen_slbmfee(DisasContext *ctx)
4266{
4267#if defined(CONFIG_USER_ONLY)
4268 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4269#else
4270 if (unlikely(!ctx->mem_idx)) {
4271 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4272 return;
4273 }
4274 gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)],
4275 cpu_gpr[rB(ctx->opcode)]);
4276#endif
4277}
4278
4279static void gen_slbmfev(DisasContext *ctx)
4280{
4281#if defined(CONFIG_USER_ONLY)
4282 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4283#else
4284 if (unlikely(!ctx->mem_idx)) {
4285 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
4286 return;
4287 }
4288 gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)],
4289 cpu_gpr[rB(ctx->opcode)]);
4290#endif
4291}
12de9a39
JM
4292#endif /* defined(TARGET_PPC64) */
4293
79aceca5 4294/*** Lookaside buffer management ***/
76db3ba4 4295/* Optional & mem_idx only: */
99e300ef 4296
54623277 4297/* tlbia */
99e300ef 4298static void gen_tlbia(DisasContext *ctx)
79aceca5 4299{
9a64fbe4 4300#if defined(CONFIG_USER_ONLY)
e06fcd75 4301 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9a64fbe4 4302#else
76db3ba4 4303 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4304 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 4305 return;
9a64fbe4 4306 }
74d37793 4307 gen_helper_tlbia();
9a64fbe4 4308#endif
79aceca5
FB
4309}
4310
bf14b1ce 4311/* tlbiel */
99e300ef 4312static void gen_tlbiel(DisasContext *ctx)
bf14b1ce
BS
4313{
4314#if defined(CONFIG_USER_ONLY)
4315 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4316#else
4317 if (unlikely(!ctx->mem_idx)) {
4318 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
4319 return;
4320 }
4321 gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
4322#endif
4323}
4324
79aceca5 4325/* tlbie */
99e300ef 4326static void gen_tlbie(DisasContext *ctx)
79aceca5 4327{
9a64fbe4 4328#if defined(CONFIG_USER_ONLY)
e06fcd75 4329 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9a64fbe4 4330#else
76db3ba4 4331 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4332 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 4333 return;
9a64fbe4 4334 }
d9bce9d9 4335#if defined(TARGET_PPC64)
74d37793
AJ
4336 if (!ctx->sf_mode) {
4337 TCGv t0 = tcg_temp_new();
4338 tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
4339 gen_helper_tlbie(t0);
4340 tcg_temp_free(t0);
4341 } else
d9bce9d9 4342#endif
74d37793 4343 gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
9a64fbe4 4344#endif
79aceca5
FB
4345}
4346
4347/* tlbsync */
99e300ef 4348static void gen_tlbsync(DisasContext *ctx)
79aceca5 4349{
9a64fbe4 4350#if defined(CONFIG_USER_ONLY)
e06fcd75 4351 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9a64fbe4 4352#else
76db3ba4 4353 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4354 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
9fddaa0c 4355 return;
9a64fbe4
FB
4356 }
4357 /* This has no effect: it should ensure that all previous
4358 * tlbie have completed
4359 */
e06fcd75 4360 gen_stop_exception(ctx);
9a64fbe4 4361#endif
79aceca5
FB
4362}
4363
426613db
JM
4364#if defined(TARGET_PPC64)
4365/* slbia */
99e300ef 4366static void gen_slbia(DisasContext *ctx)
426613db
JM
4367{
4368#if defined(CONFIG_USER_ONLY)
e06fcd75 4369 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db 4370#else
76db3ba4 4371 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4372 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db
JM
4373 return;
4374 }
74d37793 4375 gen_helper_slbia();
426613db
JM
4376#endif
4377}
4378
4379/* slbie */
99e300ef 4380static void gen_slbie(DisasContext *ctx)
426613db
JM
4381{
4382#if defined(CONFIG_USER_ONLY)
e06fcd75 4383 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db 4384#else
76db3ba4 4385 if (unlikely(!ctx->mem_idx)) {
e06fcd75 4386 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
426613db
JM
4387 return;
4388 }
74d37793 4389 gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]);
426613db
JM
4390#endif
4391}
4392#endif
4393
79aceca5
FB
4394/*** External control ***/
4395/* Optional: */
99e300ef 4396
54623277 4397/* eciwx */
99e300ef 4398static void gen_eciwx(DisasContext *ctx)
79aceca5 4399{
76db3ba4 4400 TCGv t0;
fa407c03 4401 /* Should check EAR[E] ! */
76db3ba4
AJ
4402 gen_set_access_type(ctx, ACCESS_EXT);
4403 t0 = tcg_temp_new();
4404 gen_addr_reg_index(ctx, t0);
fa407c03 4405 gen_check_align(ctx, t0, 0x03);
76db3ba4 4406 gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0);
fa407c03 4407 tcg_temp_free(t0);
76a66253
JM
4408}
4409
4410/* ecowx */
99e300ef 4411static void gen_ecowx(DisasContext *ctx)
76a66253 4412{
76db3ba4 4413 TCGv t0;
fa407c03 4414 /* Should check EAR[E] ! */
76db3ba4
AJ
4415 gen_set_access_type(ctx, ACCESS_EXT);
4416 t0 = tcg_temp_new();
4417 gen_addr_reg_index(ctx, t0);
fa407c03 4418 gen_check_align(ctx, t0, 0x03);
76db3ba4 4419 gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0);
fa407c03 4420 tcg_temp_free(t0);
76a66253
JM
4421}
4422
4423/* PowerPC 601 specific instructions */
99e300ef 4424
54623277 4425/* abs - abs. */
99e300ef 4426static void gen_abs(DisasContext *ctx)
76a66253 4427{
22e0e173
AJ
4428 int l1 = gen_new_label();
4429 int l2 = gen_new_label();
4430 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4431 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4432 tcg_gen_br(l2);
4433 gen_set_label(l1);
4434 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4435 gen_set_label(l2);
76a66253 4436 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4437 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4438}
4439
4440/* abso - abso. */
99e300ef 4441static void gen_abso(DisasContext *ctx)
76a66253 4442{
22e0e173
AJ
4443 int l1 = gen_new_label();
4444 int l2 = gen_new_label();
4445 int l3 = gen_new_label();
4446 /* Start with XER OV disabled, the most likely case */
4447 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4448 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4449 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4450 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4451 tcg_gen_br(l2);
4452 gen_set_label(l1);
4453 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4454 tcg_gen_br(l3);
4455 gen_set_label(l2);
4456 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4457 gen_set_label(l3);
76a66253 4458 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4459 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4460}
4461
4462/* clcs */
99e300ef 4463static void gen_clcs(DisasContext *ctx)
76a66253 4464{
22e0e173
AJ
4465 TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4466 gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
4467 tcg_temp_free_i32(t0);
c7697e1f 4468 /* Rc=1 sets CR0 to an undefined state */
76a66253
JM
4469}
4470
4471/* div - div. */
99e300ef 4472static void gen_div(DisasContext *ctx)
76a66253 4473{
22e0e173 4474 gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 4475 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4476 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4477}
4478
4479/* divo - divo. */
99e300ef 4480static void gen_divo(DisasContext *ctx)
76a66253 4481{
22e0e173 4482 gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 4483 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4484 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4485}
4486
4487/* divs - divs. */
99e300ef 4488static void gen_divs(DisasContext *ctx)
76a66253 4489{
22e0e173 4490 gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 4491 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4492 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4493}
4494
4495/* divso - divso. */
99e300ef 4496static void gen_divso(DisasContext *ctx)
76a66253 4497{
22e0e173 4498 gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 4499 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4500 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4501}
4502
4503/* doz - doz. */
99e300ef 4504static void gen_doz(DisasContext *ctx)
76a66253 4505{
22e0e173
AJ
4506 int l1 = gen_new_label();
4507 int l2 = gen_new_label();
4508 tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4509 tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4510 tcg_gen_br(l2);
4511 gen_set_label(l1);
4512 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4513 gen_set_label(l2);
76a66253 4514 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4515 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4516}
4517
4518/* dozo - dozo. */
99e300ef 4519static void gen_dozo(DisasContext *ctx)
76a66253 4520{
22e0e173
AJ
4521 int l1 = gen_new_label();
4522 int l2 = gen_new_label();
4523 TCGv t0 = tcg_temp_new();
4524 TCGv t1 = tcg_temp_new();
4525 TCGv t2 = tcg_temp_new();
4526 /* Start with XER OV disabled, the most likely case */
4527 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4528 tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4529 tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4530 tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4531 tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4532 tcg_gen_andc_tl(t1, t1, t2);
4533 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4534 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4535 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4536 tcg_gen_br(l2);
4537 gen_set_label(l1);
4538 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4539 gen_set_label(l2);
4540 tcg_temp_free(t0);
4541 tcg_temp_free(t1);
4542 tcg_temp_free(t2);
76a66253 4543 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4544 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4545}
4546
4547/* dozi */
99e300ef 4548static void gen_dozi(DisasContext *ctx)
76a66253 4549{
22e0e173
AJ
4550 target_long simm = SIMM(ctx->opcode);
4551 int l1 = gen_new_label();
4552 int l2 = gen_new_label();
4553 tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4554 tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4555 tcg_gen_br(l2);
4556 gen_set_label(l1);
4557 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4558 gen_set_label(l2);
4559 if (unlikely(Rc(ctx->opcode) != 0))
4560 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4561}
4562
76a66253 4563/* lscbx - lscbx. */
99e300ef 4564static void gen_lscbx(DisasContext *ctx)
76a66253 4565{
bdb4b689
AJ
4566 TCGv t0 = tcg_temp_new();
4567 TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4568 TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4569 TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
76a66253 4570
76db3ba4 4571 gen_addr_reg_index(ctx, t0);
76a66253 4572 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4573 gen_update_nip(ctx, ctx->nip - 4);
bdb4b689
AJ
4574 gen_helper_lscbx(t0, t0, t1, t2, t3);
4575 tcg_temp_free_i32(t1);
4576 tcg_temp_free_i32(t2);
4577 tcg_temp_free_i32(t3);
3d7b417e 4578 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
bdb4b689 4579 tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
76a66253 4580 if (unlikely(Rc(ctx->opcode) != 0))
bdb4b689
AJ
4581 gen_set_Rc0(ctx, t0);
4582 tcg_temp_free(t0);
76a66253
JM
4583}
4584
4585/* maskg - maskg. */
99e300ef 4586static void gen_maskg(DisasContext *ctx)
76a66253 4587{
22e0e173
AJ
4588 int l1 = gen_new_label();
4589 TCGv t0 = tcg_temp_new();
4590 TCGv t1 = tcg_temp_new();
4591 TCGv t2 = tcg_temp_new();
4592 TCGv t3 = tcg_temp_new();
4593 tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4594 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4595 tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4596 tcg_gen_addi_tl(t2, t0, 1);
4597 tcg_gen_shr_tl(t2, t3, t2);
4598 tcg_gen_shr_tl(t3, t3, t1);
4599 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4600 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4601 tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4602 gen_set_label(l1);
4603 tcg_temp_free(t0);
4604 tcg_temp_free(t1);
4605 tcg_temp_free(t2);
4606 tcg_temp_free(t3);
76a66253 4607 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4608 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4609}
4610
4611/* maskir - maskir. */
99e300ef 4612static void gen_maskir(DisasContext *ctx)
76a66253 4613{
22e0e173
AJ
4614 TCGv t0 = tcg_temp_new();
4615 TCGv t1 = tcg_temp_new();
4616 tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4617 tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4618 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4619 tcg_temp_free(t0);
4620 tcg_temp_free(t1);
76a66253 4621 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4622 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4623}
4624
4625/* mul - mul. */
99e300ef 4626static void gen_mul(DisasContext *ctx)
76a66253 4627{
22e0e173
AJ
4628 TCGv_i64 t0 = tcg_temp_new_i64();
4629 TCGv_i64 t1 = tcg_temp_new_i64();
4630 TCGv t2 = tcg_temp_new();
4631 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4632 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4633 tcg_gen_mul_i64(t0, t0, t1);
4634 tcg_gen_trunc_i64_tl(t2, t0);
4635 gen_store_spr(SPR_MQ, t2);
4636 tcg_gen_shri_i64(t1, t0, 32);
4637 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4638 tcg_temp_free_i64(t0);
4639 tcg_temp_free_i64(t1);
4640 tcg_temp_free(t2);
76a66253 4641 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4642 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4643}
4644
4645/* mulo - mulo. */
99e300ef 4646static void gen_mulo(DisasContext *ctx)
76a66253 4647{
22e0e173
AJ
4648 int l1 = gen_new_label();
4649 TCGv_i64 t0 = tcg_temp_new_i64();
4650 TCGv_i64 t1 = tcg_temp_new_i64();
4651 TCGv t2 = tcg_temp_new();
4652 /* Start with XER OV disabled, the most likely case */
4653 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4654 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4655 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4656 tcg_gen_mul_i64(t0, t0, t1);
4657 tcg_gen_trunc_i64_tl(t2, t0);
4658 gen_store_spr(SPR_MQ, t2);
4659 tcg_gen_shri_i64(t1, t0, 32);
4660 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4661 tcg_gen_ext32s_i64(t1, t0);
4662 tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4663 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4664 gen_set_label(l1);
4665 tcg_temp_free_i64(t0);
4666 tcg_temp_free_i64(t1);
4667 tcg_temp_free(t2);
76a66253 4668 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4669 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4670}
4671
4672/* nabs - nabs. */
99e300ef 4673static void gen_nabs(DisasContext *ctx)
76a66253 4674{
22e0e173
AJ
4675 int l1 = gen_new_label();
4676 int l2 = gen_new_label();
4677 tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4678 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4679 tcg_gen_br(l2);
4680 gen_set_label(l1);
4681 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4682 gen_set_label(l2);
76a66253 4683 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4684 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4685}
4686
4687/* nabso - nabso. */
99e300ef 4688static void gen_nabso(DisasContext *ctx)
76a66253 4689{
22e0e173
AJ
4690 int l1 = gen_new_label();
4691 int l2 = gen_new_label();
4692 tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4693 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4694 tcg_gen_br(l2);
4695 gen_set_label(l1);
4696 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4697 gen_set_label(l2);
4698 /* nabs never overflows */
4699 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
76a66253 4700 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4701 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4702}
4703
4704/* rlmi - rlmi. */
99e300ef 4705static void gen_rlmi(DisasContext *ctx)
76a66253 4706{
7487953d
AJ
4707 uint32_t mb = MB(ctx->opcode);
4708 uint32_t me = ME(ctx->opcode);
4709 TCGv t0 = tcg_temp_new();
4710 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4711 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4712 tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4713 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4714 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4715 tcg_temp_free(t0);
76a66253 4716 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4717 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4718}
4719
4720/* rrib - rrib. */
99e300ef 4721static void gen_rrib(DisasContext *ctx)
76a66253 4722{
7487953d
AJ
4723 TCGv t0 = tcg_temp_new();
4724 TCGv t1 = tcg_temp_new();
4725 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4726 tcg_gen_movi_tl(t1, 0x80000000);
4727 tcg_gen_shr_tl(t1, t1, t0);
4728 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4729 tcg_gen_and_tl(t0, t0, t1);
4730 tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4731 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4732 tcg_temp_free(t0);
4733 tcg_temp_free(t1);
76a66253 4734 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4735 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4736}
4737
4738/* sle - sle. */
99e300ef 4739static void gen_sle(DisasContext *ctx)
76a66253 4740{
7487953d
AJ
4741 TCGv t0 = tcg_temp_new();
4742 TCGv t1 = tcg_temp_new();
4743 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4744 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4745 tcg_gen_subfi_tl(t1, 32, t1);
4746 tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4747 tcg_gen_or_tl(t1, t0, t1);
4748 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4749 gen_store_spr(SPR_MQ, t1);
4750 tcg_temp_free(t0);
4751 tcg_temp_free(t1);
76a66253 4752 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4753 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4754}
4755
4756/* sleq - sleq. */
99e300ef 4757static void gen_sleq(DisasContext *ctx)
76a66253 4758{
7487953d
AJ
4759 TCGv t0 = tcg_temp_new();
4760 TCGv t1 = tcg_temp_new();
4761 TCGv t2 = tcg_temp_new();
4762 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4763 tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4764 tcg_gen_shl_tl(t2, t2, t0);
4765 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4766 gen_load_spr(t1, SPR_MQ);
4767 gen_store_spr(SPR_MQ, t0);
4768 tcg_gen_and_tl(t0, t0, t2);
4769 tcg_gen_andc_tl(t1, t1, t2);
4770 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4771 tcg_temp_free(t0);
4772 tcg_temp_free(t1);
4773 tcg_temp_free(t2);
76a66253 4774 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4775 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4776}
4777
4778/* sliq - sliq. */
99e300ef 4779static void gen_sliq(DisasContext *ctx)
76a66253 4780{
7487953d
AJ
4781 int sh = SH(ctx->opcode);
4782 TCGv t0 = tcg_temp_new();
4783 TCGv t1 = tcg_temp_new();
4784 tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4785 tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4786 tcg_gen_or_tl(t1, t0, t1);
4787 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4788 gen_store_spr(SPR_MQ, t1);
4789 tcg_temp_free(t0);
4790 tcg_temp_free(t1);
76a66253 4791 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4792 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4793}
4794
4795/* slliq - slliq. */
99e300ef 4796static void gen_slliq(DisasContext *ctx)
76a66253 4797{
7487953d
AJ
4798 int sh = SH(ctx->opcode);
4799 TCGv t0 = tcg_temp_new();
4800 TCGv t1 = tcg_temp_new();
4801 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4802 gen_load_spr(t1, SPR_MQ);
4803 gen_store_spr(SPR_MQ, t0);
4804 tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh));
4805 tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
4806 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4807 tcg_temp_free(t0);
4808 tcg_temp_free(t1);
76a66253 4809 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4810 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4811}
4812
4813/* sllq - sllq. */
99e300ef 4814static void gen_sllq(DisasContext *ctx)
76a66253 4815{
7487953d
AJ
4816 int l1 = gen_new_label();
4817 int l2 = gen_new_label();
4818 TCGv t0 = tcg_temp_local_new();
4819 TCGv t1 = tcg_temp_local_new();
4820 TCGv t2 = tcg_temp_local_new();
4821 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4822 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4823 tcg_gen_shl_tl(t1, t1, t2);
4824 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4825 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4826 gen_load_spr(t0, SPR_MQ);
4827 tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4828 tcg_gen_br(l2);
4829 gen_set_label(l1);
4830 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4831 gen_load_spr(t2, SPR_MQ);
4832 tcg_gen_andc_tl(t1, t2, t1);
4833 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4834 gen_set_label(l2);
4835 tcg_temp_free(t0);
4836 tcg_temp_free(t1);
4837 tcg_temp_free(t2);
76a66253 4838 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4839 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4840}
4841
4842/* slq - slq. */
99e300ef 4843static void gen_slq(DisasContext *ctx)
76a66253 4844{
7487953d
AJ
4845 int l1 = gen_new_label();
4846 TCGv t0 = tcg_temp_new();
4847 TCGv t1 = tcg_temp_new();
4848 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4849 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4850 tcg_gen_subfi_tl(t1, 32, t1);
4851 tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4852 tcg_gen_or_tl(t1, t0, t1);
4853 gen_store_spr(SPR_MQ, t1);
4854 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4855 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4856 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4857 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4858 gen_set_label(l1);
4859 tcg_temp_free(t0);
4860 tcg_temp_free(t1);
76a66253 4861 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4862 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4863}
4864
d9bce9d9 4865/* sraiq - sraiq. */
99e300ef 4866static void gen_sraiq(DisasContext *ctx)
76a66253 4867{
7487953d
AJ
4868 int sh = SH(ctx->opcode);
4869 int l1 = gen_new_label();
4870 TCGv t0 = tcg_temp_new();
4871 TCGv t1 = tcg_temp_new();
4872 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4873 tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4874 tcg_gen_or_tl(t0, t0, t1);
4875 gen_store_spr(SPR_MQ, t0);
4876 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4877 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4878 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4879 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4880 gen_set_label(l1);
4881 tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
4882 tcg_temp_free(t0);
4883 tcg_temp_free(t1);
76a66253 4884 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4885 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4886}
4887
4888/* sraq - sraq. */
99e300ef 4889static void gen_sraq(DisasContext *ctx)
76a66253 4890{
7487953d
AJ
4891 int l1 = gen_new_label();
4892 int l2 = gen_new_label();
4893 TCGv t0 = tcg_temp_new();
4894 TCGv t1 = tcg_temp_local_new();
4895 TCGv t2 = tcg_temp_local_new();
4896 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4897 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4898 tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
4899 tcg_gen_subfi_tl(t2, 32, t2);
4900 tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
4901 tcg_gen_or_tl(t0, t0, t2);
4902 gen_store_spr(SPR_MQ, t0);
4903 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4904 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
4905 tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
4906 tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
4907 gen_set_label(l1);
4908 tcg_temp_free(t0);
4909 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4910 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4911 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4912 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4913 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4914 gen_set_label(l2);
4915 tcg_temp_free(t1);
4916 tcg_temp_free(t2);
76a66253 4917 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4918 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4919}
4920
4921/* sre - sre. */
99e300ef 4922static void gen_sre(DisasContext *ctx)
76a66253 4923{
7487953d
AJ
4924 TCGv t0 = tcg_temp_new();
4925 TCGv t1 = tcg_temp_new();
4926 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4927 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4928 tcg_gen_subfi_tl(t1, 32, t1);
4929 tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4930 tcg_gen_or_tl(t1, t0, t1);
4931 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4932 gen_store_spr(SPR_MQ, t1);
4933 tcg_temp_free(t0);
4934 tcg_temp_free(t1);
76a66253 4935 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4936 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4937}
4938
4939/* srea - srea. */
99e300ef 4940static void gen_srea(DisasContext *ctx)
76a66253 4941{
7487953d
AJ
4942 TCGv t0 = tcg_temp_new();
4943 TCGv t1 = tcg_temp_new();
4944 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4945 tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4946 gen_store_spr(SPR_MQ, t0);
4947 tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
4948 tcg_temp_free(t0);
4949 tcg_temp_free(t1);
76a66253 4950 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4951 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4952}
4953
4954/* sreq */
99e300ef 4955static void gen_sreq(DisasContext *ctx)
76a66253 4956{
7487953d
AJ
4957 TCGv t0 = tcg_temp_new();
4958 TCGv t1 = tcg_temp_new();
4959 TCGv t2 = tcg_temp_new();
4960 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4961 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4962 tcg_gen_shr_tl(t1, t1, t0);
4963 tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4964 gen_load_spr(t2, SPR_MQ);
4965 gen_store_spr(SPR_MQ, t0);
4966 tcg_gen_and_tl(t0, t0, t1);
4967 tcg_gen_andc_tl(t2, t2, t1);
4968 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4969 tcg_temp_free(t0);
4970 tcg_temp_free(t1);
4971 tcg_temp_free(t2);
76a66253 4972 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4973 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4974}
4975
4976/* sriq */
99e300ef 4977static void gen_sriq(DisasContext *ctx)
76a66253 4978{
7487953d
AJ
4979 int sh = SH(ctx->opcode);
4980 TCGv t0 = tcg_temp_new();
4981 TCGv t1 = tcg_temp_new();
4982 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4983 tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4984 tcg_gen_or_tl(t1, t0, t1);
4985 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4986 gen_store_spr(SPR_MQ, t1);
4987 tcg_temp_free(t0);
4988 tcg_temp_free(t1);
76a66253 4989 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4990 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4991}
4992
4993/* srliq */
99e300ef 4994static void gen_srliq(DisasContext *ctx)
76a66253 4995{
7487953d
AJ
4996 int sh = SH(ctx->opcode);
4997 TCGv t0 = tcg_temp_new();
4998 TCGv t1 = tcg_temp_new();
4999 tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5000 gen_load_spr(t1, SPR_MQ);
5001 gen_store_spr(SPR_MQ, t0);
5002 tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh));
5003 tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
5004 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5005 tcg_temp_free(t0);
5006 tcg_temp_free(t1);
76a66253 5007 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5008 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5009}
5010
5011/* srlq */
99e300ef 5012static void gen_srlq(DisasContext *ctx)
76a66253 5013{
7487953d
AJ
5014 int l1 = gen_new_label();
5015 int l2 = gen_new_label();
5016 TCGv t0 = tcg_temp_local_new();
5017 TCGv t1 = tcg_temp_local_new();
5018 TCGv t2 = tcg_temp_local_new();
5019 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5020 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5021 tcg_gen_shr_tl(t2, t1, t2);
5022 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5023 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5024 gen_load_spr(t0, SPR_MQ);
5025 tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5026 tcg_gen_br(l2);
5027 gen_set_label(l1);
5028 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5029 tcg_gen_and_tl(t0, t0, t2);
5030 gen_load_spr(t1, SPR_MQ);
5031 tcg_gen_andc_tl(t1, t1, t2);
5032 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5033 gen_set_label(l2);
5034 tcg_temp_free(t0);
5035 tcg_temp_free(t1);
5036 tcg_temp_free(t2);
76a66253 5037 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5038 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5039}
5040
5041/* srq */
99e300ef 5042static void gen_srq(DisasContext *ctx)
76a66253 5043{
7487953d
AJ
5044 int l1 = gen_new_label();
5045 TCGv t0 = tcg_temp_new();
5046 TCGv t1 = tcg_temp_new();
5047 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5048 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5049 tcg_gen_subfi_tl(t1, 32, t1);
5050 tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5051 tcg_gen_or_tl(t1, t0, t1);
5052 gen_store_spr(SPR_MQ, t1);
5053 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5054 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5055 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5056 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5057 gen_set_label(l1);
5058 tcg_temp_free(t0);
5059 tcg_temp_free(t1);
76a66253 5060 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5061 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5062}
5063
5064/* PowerPC 602 specific instructions */
99e300ef 5065
54623277 5066/* dsa */
99e300ef 5067static void gen_dsa(DisasContext *ctx)
76a66253
JM
5068{
5069 /* XXX: TODO */
e06fcd75 5070 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5071}
5072
5073/* esa */
99e300ef 5074static void gen_esa(DisasContext *ctx)
76a66253
JM
5075{
5076 /* XXX: TODO */
e06fcd75 5077 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5078}
5079
5080/* mfrom */
99e300ef 5081static void gen_mfrom(DisasContext *ctx)
76a66253
JM
5082{
5083#if defined(CONFIG_USER_ONLY)
e06fcd75 5084 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5085#else
76db3ba4 5086 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5087 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5088 return;
5089 }
cf02a65c 5090 gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5091#endif
5092}
5093
5094/* 602 - 603 - G2 TLB management */
e8eaa2c0 5095
54623277 5096/* tlbld */
e8eaa2c0 5097static void gen_tlbld_6xx(DisasContext *ctx)
76a66253
JM
5098{
5099#if defined(CONFIG_USER_ONLY)
e06fcd75 5100 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5101#else
76db3ba4 5102 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5103 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5104 return;
5105 }
74d37793 5106 gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
5107#endif
5108}
5109
5110/* tlbli */
e8eaa2c0 5111static void gen_tlbli_6xx(DisasContext *ctx)
76a66253
JM
5112{
5113#if defined(CONFIG_USER_ONLY)
e06fcd75 5114 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5115#else
76db3ba4 5116 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5117 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5118 return;
5119 }
74d37793 5120 gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
5121#endif
5122}
5123
7dbe11ac 5124/* 74xx TLB management */
e8eaa2c0 5125
54623277 5126/* tlbld */
e8eaa2c0 5127static void gen_tlbld_74xx(DisasContext *ctx)
7dbe11ac
JM
5128{
5129#if defined(CONFIG_USER_ONLY)
e06fcd75 5130 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
7dbe11ac 5131#else
76db3ba4 5132 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5133 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
7dbe11ac
JM
5134 return;
5135 }
74d37793 5136 gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
5137#endif
5138}
5139
5140/* tlbli */
e8eaa2c0 5141static void gen_tlbli_74xx(DisasContext *ctx)
7dbe11ac
JM
5142{
5143#if defined(CONFIG_USER_ONLY)
e06fcd75 5144 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
7dbe11ac 5145#else
76db3ba4 5146 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5147 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
7dbe11ac
JM
5148 return;
5149 }
74d37793 5150 gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
5151#endif
5152}
5153
76a66253 5154/* POWER instructions not in PowerPC 601 */
99e300ef 5155
54623277 5156/* clf */
99e300ef 5157static void gen_clf(DisasContext *ctx)
76a66253
JM
5158{
5159 /* Cache line flush: implemented as no-op */
5160}
5161
5162/* cli */
99e300ef 5163static void gen_cli(DisasContext *ctx)
76a66253 5164{
7f75ffd3 5165 /* Cache line invalidate: privileged and treated as no-op */
76a66253 5166#if defined(CONFIG_USER_ONLY)
e06fcd75 5167 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5168#else
76db3ba4 5169 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5170 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5171 return;
5172 }
5173#endif
5174}
5175
5176/* dclst */
99e300ef 5177static void gen_dclst(DisasContext *ctx)
76a66253
JM
5178{
5179 /* Data cache line store: treated as no-op */
5180}
5181
99e300ef 5182static void gen_mfsri(DisasContext *ctx)
76a66253
JM
5183{
5184#if defined(CONFIG_USER_ONLY)
e06fcd75 5185 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5186#else
74d37793
AJ
5187 int ra = rA(ctx->opcode);
5188 int rd = rD(ctx->opcode);
5189 TCGv t0;
76db3ba4 5190 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5191 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5192 return;
5193 }
74d37793 5194 t0 = tcg_temp_new();
76db3ba4 5195 gen_addr_reg_index(ctx, t0);
74d37793
AJ
5196 tcg_gen_shri_tl(t0, t0, 28);
5197 tcg_gen_andi_tl(t0, t0, 0xF);
5198 gen_helper_load_sr(cpu_gpr[rd], t0);
5199 tcg_temp_free(t0);
76a66253 5200 if (ra != 0 && ra != rd)
74d37793 5201 tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
76a66253
JM
5202#endif
5203}
5204
99e300ef 5205static void gen_rac(DisasContext *ctx)
76a66253
JM
5206{
5207#if defined(CONFIG_USER_ONLY)
e06fcd75 5208 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5209#else
22e0e173 5210 TCGv t0;
76db3ba4 5211 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5212 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5213 return;
5214 }
22e0e173 5215 t0 = tcg_temp_new();
76db3ba4 5216 gen_addr_reg_index(ctx, t0);
22e0e173
AJ
5217 gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
5218 tcg_temp_free(t0);
76a66253
JM
5219#endif
5220}
5221
99e300ef 5222static void gen_rfsvc(DisasContext *ctx)
76a66253
JM
5223{
5224#if defined(CONFIG_USER_ONLY)
e06fcd75 5225 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5226#else
76db3ba4 5227 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5228 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5229 return;
5230 }
d72a19f7 5231 gen_helper_rfsvc();
e06fcd75 5232 gen_sync_exception(ctx);
76a66253
JM
5233#endif
5234}
5235
5236/* svc is not implemented for now */
5237
5238/* POWER2 specific instructions */
5239/* Quad manipulation (load/store two floats at a time) */
76a66253
JM
5240
5241/* lfq */
99e300ef 5242static void gen_lfq(DisasContext *ctx)
76a66253 5243{
01a4afeb 5244 int rd = rD(ctx->opcode);
76db3ba4
AJ
5245 TCGv t0;
5246 gen_set_access_type(ctx, ACCESS_FLOAT);
5247 t0 = tcg_temp_new();
5248 gen_addr_imm_index(ctx, t0, 0);
5249 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5250 gen_addr_add(ctx, t0, t0, 8);
5251 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5252 tcg_temp_free(t0);
76a66253
JM
5253}
5254
5255/* lfqu */
99e300ef 5256static void gen_lfqu(DisasContext *ctx)
76a66253
JM
5257{
5258 int ra = rA(ctx->opcode);
01a4afeb 5259 int rd = rD(ctx->opcode);
76db3ba4
AJ
5260 TCGv t0, t1;
5261 gen_set_access_type(ctx, ACCESS_FLOAT);
5262 t0 = tcg_temp_new();
5263 t1 = tcg_temp_new();
5264 gen_addr_imm_index(ctx, t0, 0);
5265 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5266 gen_addr_add(ctx, t1, t0, 8);
5267 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
76a66253 5268 if (ra != 0)
01a4afeb
AJ
5269 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5270 tcg_temp_free(t0);
5271 tcg_temp_free(t1);
76a66253
JM
5272}
5273
5274/* lfqux */
99e300ef 5275static void gen_lfqux(DisasContext *ctx)
76a66253
JM
5276{
5277 int ra = rA(ctx->opcode);
01a4afeb 5278 int rd = rD(ctx->opcode);
76db3ba4
AJ
5279 gen_set_access_type(ctx, ACCESS_FLOAT);
5280 TCGv t0, t1;
5281 t0 = tcg_temp_new();
5282 gen_addr_reg_index(ctx, t0);
5283 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5284 t1 = tcg_temp_new();
5285 gen_addr_add(ctx, t1, t0, 8);
5286 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5287 tcg_temp_free(t1);
76a66253 5288 if (ra != 0)
01a4afeb
AJ
5289 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5290 tcg_temp_free(t0);
76a66253
JM
5291}
5292
5293/* lfqx */
99e300ef 5294static void gen_lfqx(DisasContext *ctx)
76a66253 5295{
01a4afeb 5296 int rd = rD(ctx->opcode);
76db3ba4
AJ
5297 TCGv t0;
5298 gen_set_access_type(ctx, ACCESS_FLOAT);
5299 t0 = tcg_temp_new();
5300 gen_addr_reg_index(ctx, t0);
5301 gen_qemu_ld64(ctx, cpu_fpr[rd], t0);
5302 gen_addr_add(ctx, t0, t0, 8);
5303 gen_qemu_ld64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5304 tcg_temp_free(t0);
76a66253
JM
5305}
5306
5307/* stfq */
99e300ef 5308static void gen_stfq(DisasContext *ctx)
76a66253 5309{
01a4afeb 5310 int rd = rD(ctx->opcode);
76db3ba4
AJ
5311 TCGv t0;
5312 gen_set_access_type(ctx, ACCESS_FLOAT);
5313 t0 = tcg_temp_new();
5314 gen_addr_imm_index(ctx, t0, 0);
5315 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5316 gen_addr_add(ctx, t0, t0, 8);
5317 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5318 tcg_temp_free(t0);
76a66253
JM
5319}
5320
5321/* stfqu */
99e300ef 5322static void gen_stfqu(DisasContext *ctx)
76a66253
JM
5323{
5324 int ra = rA(ctx->opcode);
01a4afeb 5325 int rd = rD(ctx->opcode);
76db3ba4
AJ
5326 TCGv t0, t1;
5327 gen_set_access_type(ctx, ACCESS_FLOAT);
5328 t0 = tcg_temp_new();
5329 gen_addr_imm_index(ctx, t0, 0);
5330 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5331 t1 = tcg_temp_new();
5332 gen_addr_add(ctx, t1, t0, 8);
5333 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5334 tcg_temp_free(t1);
76a66253 5335 if (ra != 0)
01a4afeb
AJ
5336 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5337 tcg_temp_free(t0);
76a66253
JM
5338}
5339
5340/* stfqux */
99e300ef 5341static void gen_stfqux(DisasContext *ctx)
76a66253
JM
5342{
5343 int ra = rA(ctx->opcode);
01a4afeb 5344 int rd = rD(ctx->opcode);
76db3ba4
AJ
5345 TCGv t0, t1;
5346 gen_set_access_type(ctx, ACCESS_FLOAT);
5347 t0 = tcg_temp_new();
5348 gen_addr_reg_index(ctx, t0);
5349 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5350 t1 = tcg_temp_new();
5351 gen_addr_add(ctx, t1, t0, 8);
5352 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t1);
5353 tcg_temp_free(t1);
76a66253 5354 if (ra != 0)
01a4afeb
AJ
5355 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5356 tcg_temp_free(t0);
76a66253
JM
5357}
5358
5359/* stfqx */
99e300ef 5360static void gen_stfqx(DisasContext *ctx)
76a66253 5361{
01a4afeb 5362 int rd = rD(ctx->opcode);
76db3ba4
AJ
5363 TCGv t0;
5364 gen_set_access_type(ctx, ACCESS_FLOAT);
5365 t0 = tcg_temp_new();
5366 gen_addr_reg_index(ctx, t0);
5367 gen_qemu_st64(ctx, cpu_fpr[rd], t0);
5368 gen_addr_add(ctx, t0, t0, 8);
5369 gen_qemu_st64(ctx, cpu_fpr[(rd + 1) % 32], t0);
01a4afeb 5370 tcg_temp_free(t0);
76a66253
JM
5371}
5372
5373/* BookE specific instructions */
99e300ef 5374
54623277 5375/* XXX: not implemented on 440 ? */
99e300ef 5376static void gen_mfapidi(DisasContext *ctx)
76a66253
JM
5377{
5378 /* XXX: TODO */
e06fcd75 5379 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253
JM
5380}
5381
2662a059 5382/* XXX: not implemented on 440 ? */
99e300ef 5383static void gen_tlbiva(DisasContext *ctx)
76a66253
JM
5384{
5385#if defined(CONFIG_USER_ONLY)
e06fcd75 5386 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5387#else
74d37793 5388 TCGv t0;
76db3ba4 5389 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5390 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5391 return;
5392 }
ec72e276 5393 t0 = tcg_temp_new();
76db3ba4 5394 gen_addr_reg_index(ctx, t0);
74d37793
AJ
5395 gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
5396 tcg_temp_free(t0);
76a66253
JM
5397#endif
5398}
5399
5400/* All 405 MAC instructions are translated here */
636aa200
BS
5401static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3,
5402 int ra, int rb, int rt, int Rc)
76a66253 5403{
182608d4
AJ
5404 TCGv t0, t1;
5405
a7812ae4
PB
5406 t0 = tcg_temp_local_new();
5407 t1 = tcg_temp_local_new();
182608d4 5408
76a66253
JM
5409 switch (opc3 & 0x0D) {
5410 case 0x05:
5411 /* macchw - macchw. - macchwo - macchwo. */
5412 /* macchws - macchws. - macchwso - macchwso. */
5413 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5414 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5415 /* mulchw - mulchw. */
182608d4
AJ
5416 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5417 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5418 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5419 break;
5420 case 0x04:
5421 /* macchwu - macchwu. - macchwuo - macchwuo. */
5422 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5423 /* mulchwu - mulchwu. */
182608d4
AJ
5424 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5425 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5426 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5427 break;
5428 case 0x01:
5429 /* machhw - machhw. - machhwo - machhwo. */
5430 /* machhws - machhws. - machhwso - machhwso. */
5431 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5432 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5433 /* mulhhw - mulhhw. */
182608d4
AJ
5434 tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5435 tcg_gen_ext16s_tl(t0, t0);
5436 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5437 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5438 break;
5439 case 0x00:
5440 /* machhwu - machhwu. - machhwuo - machhwuo. */
5441 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5442 /* mulhhwu - mulhhwu. */
182608d4
AJ
5443 tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5444 tcg_gen_ext16u_tl(t0, t0);
5445 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5446 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5447 break;
5448 case 0x0D:
5449 /* maclhw - maclhw. - maclhwo - maclhwo. */
5450 /* maclhws - maclhws. - maclhwso - maclhwso. */
5451 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5452 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5453 /* mullhw - mullhw. */
182608d4
AJ
5454 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5455 tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
76a66253
JM
5456 break;
5457 case 0x0C:
5458 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5459 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5460 /* mullhwu - mullhwu. */
182608d4
AJ
5461 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5462 tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
76a66253
JM
5463 break;
5464 }
76a66253 5465 if (opc2 & 0x04) {
182608d4
AJ
5466 /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5467 tcg_gen_mul_tl(t1, t0, t1);
5468 if (opc2 & 0x02) {
5469 /* nmultiply-and-accumulate (0x0E) */
5470 tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5471 } else {
5472 /* multiply-and-accumulate (0x0C) */
5473 tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5474 }
5475
5476 if (opc3 & 0x12) {
5477 /* Check overflow and/or saturate */
5478 int l1 = gen_new_label();
5479
5480 if (opc3 & 0x10) {
5481 /* Start with XER OV disabled, the most likely case */
5482 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5483 }
5484 if (opc3 & 0x01) {
5485 /* Signed */
5486 tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5487 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5488 tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5489 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
bdc4e053 5490 if (opc3 & 0x02) {
182608d4
AJ
5491 /* Saturate */
5492 tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5493 tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5494 }
5495 } else {
5496 /* Unsigned */
5497 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
bdc4e053 5498 if (opc3 & 0x02) {
182608d4
AJ
5499 /* Saturate */
5500 tcg_gen_movi_tl(t0, UINT32_MAX);
5501 }
5502 }
5503 if (opc3 & 0x10) {
5504 /* Check overflow */
5505 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5506 }
5507 gen_set_label(l1);
5508 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5509 }
5510 } else {
5511 tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
76a66253 5512 }
182608d4
AJ
5513 tcg_temp_free(t0);
5514 tcg_temp_free(t1);
76a66253
JM
5515 if (unlikely(Rc) != 0) {
5516 /* Update Rc0 */
182608d4 5517 gen_set_Rc0(ctx, cpu_gpr[rt]);
76a66253
JM
5518 }
5519}
5520
a750fc0b 5521#define GEN_MAC_HANDLER(name, opc2, opc3) \
99e300ef 5522static void glue(gen_, name)(DisasContext *ctx) \
76a66253
JM
5523{ \
5524 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5525 rD(ctx->opcode), Rc(ctx->opcode)); \
5526}
5527
5528/* macchw - macchw. */
a750fc0b 5529GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
76a66253 5530/* macchwo - macchwo. */
a750fc0b 5531GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
76a66253 5532/* macchws - macchws. */
a750fc0b 5533GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
76a66253 5534/* macchwso - macchwso. */
a750fc0b 5535GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
76a66253 5536/* macchwsu - macchwsu. */
a750fc0b 5537GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
76a66253 5538/* macchwsuo - macchwsuo. */
a750fc0b 5539GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
76a66253 5540/* macchwu - macchwu. */
a750fc0b 5541GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
76a66253 5542/* macchwuo - macchwuo. */
a750fc0b 5543GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
76a66253 5544/* machhw - machhw. */
a750fc0b 5545GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
76a66253 5546/* machhwo - machhwo. */
a750fc0b 5547GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
76a66253 5548/* machhws - machhws. */
a750fc0b 5549GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
76a66253 5550/* machhwso - machhwso. */
a750fc0b 5551GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
76a66253 5552/* machhwsu - machhwsu. */
a750fc0b 5553GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
76a66253 5554/* machhwsuo - machhwsuo. */
a750fc0b 5555GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
76a66253 5556/* machhwu - machhwu. */
a750fc0b 5557GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
76a66253 5558/* machhwuo - machhwuo. */
a750fc0b 5559GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
76a66253 5560/* maclhw - maclhw. */
a750fc0b 5561GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
76a66253 5562/* maclhwo - maclhwo. */
a750fc0b 5563GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
76a66253 5564/* maclhws - maclhws. */
a750fc0b 5565GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
76a66253 5566/* maclhwso - maclhwso. */
a750fc0b 5567GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
76a66253 5568/* maclhwu - maclhwu. */
a750fc0b 5569GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
76a66253 5570/* maclhwuo - maclhwuo. */
a750fc0b 5571GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
76a66253 5572/* maclhwsu - maclhwsu. */
a750fc0b 5573GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
76a66253 5574/* maclhwsuo - maclhwsuo. */
a750fc0b 5575GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
76a66253 5576/* nmacchw - nmacchw. */
a750fc0b 5577GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
76a66253 5578/* nmacchwo - nmacchwo. */
a750fc0b 5579GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
76a66253 5580/* nmacchws - nmacchws. */
a750fc0b 5581GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
76a66253 5582/* nmacchwso - nmacchwso. */
a750fc0b 5583GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
76a66253 5584/* nmachhw - nmachhw. */
a750fc0b 5585GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
76a66253 5586/* nmachhwo - nmachhwo. */
a750fc0b 5587GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
76a66253 5588/* nmachhws - nmachhws. */
a750fc0b 5589GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
76a66253 5590/* nmachhwso - nmachhwso. */
a750fc0b 5591GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
76a66253 5592/* nmaclhw - nmaclhw. */
a750fc0b 5593GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
76a66253 5594/* nmaclhwo - nmaclhwo. */
a750fc0b 5595GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
76a66253 5596/* nmaclhws - nmaclhws. */
a750fc0b 5597GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
76a66253 5598/* nmaclhwso - nmaclhwso. */
a750fc0b 5599GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
76a66253
JM
5600
5601/* mulchw - mulchw. */
a750fc0b 5602GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
76a66253 5603/* mulchwu - mulchwu. */
a750fc0b 5604GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
76a66253 5605/* mulhhw - mulhhw. */
a750fc0b 5606GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
76a66253 5607/* mulhhwu - mulhhwu. */
a750fc0b 5608GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
76a66253 5609/* mullhw - mullhw. */
a750fc0b 5610GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
76a66253 5611/* mullhwu - mullhwu. */
a750fc0b 5612GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
76a66253
JM
5613
5614/* mfdcr */
99e300ef 5615static void gen_mfdcr(DisasContext *ctx)
76a66253
JM
5616{
5617#if defined(CONFIG_USER_ONLY)
e06fcd75 5618 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253 5619#else
06dca6a7 5620 TCGv dcrn;
76db3ba4 5621 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5622 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253
JM
5623 return;
5624 }
06dca6a7
AJ
5625 /* NIP cannot be restored if the memory exception comes from an helper */
5626 gen_update_nip(ctx, ctx->nip - 4);
5627 dcrn = tcg_const_tl(SPR(ctx->opcode));
5628 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
5629 tcg_temp_free(dcrn);
76a66253
JM
5630#endif
5631}
5632
5633/* mtdcr */
99e300ef 5634static void gen_mtdcr(DisasContext *ctx)
76a66253
JM
5635{
5636#if defined(CONFIG_USER_ONLY)
e06fcd75 5637 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253 5638#else
06dca6a7 5639 TCGv dcrn;
76db3ba4 5640 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5641 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
76a66253
JM
5642 return;
5643 }
06dca6a7
AJ
5644 /* NIP cannot be restored if the memory exception comes from an helper */
5645 gen_update_nip(ctx, ctx->nip - 4);
5646 dcrn = tcg_const_tl(SPR(ctx->opcode));
5647 gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
5648 tcg_temp_free(dcrn);
a42bd6cc
JM
5649#endif
5650}
5651
5652/* mfdcrx */
2662a059 5653/* XXX: not implemented on 440 ? */
99e300ef 5654static void gen_mfdcrx(DisasContext *ctx)
a42bd6cc
JM
5655{
5656#if defined(CONFIG_USER_ONLY)
e06fcd75 5657 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
a42bd6cc 5658#else
76db3ba4 5659 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5660 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
a42bd6cc
JM
5661 return;
5662 }
06dca6a7
AJ
5663 /* NIP cannot be restored if the memory exception comes from an helper */
5664 gen_update_nip(ctx, ctx->nip - 4);
5665 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
a750fc0b 5666 /* Note: Rc update flag set leads to undefined state of Rc0 */
a42bd6cc
JM
5667#endif
5668}
5669
5670/* mtdcrx */
2662a059 5671/* XXX: not implemented on 440 ? */
99e300ef 5672static void gen_mtdcrx(DisasContext *ctx)
a42bd6cc
JM
5673{
5674#if defined(CONFIG_USER_ONLY)
e06fcd75 5675 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
a42bd6cc 5676#else
76db3ba4 5677 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5678 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
a42bd6cc
JM
5679 return;
5680 }
06dca6a7
AJ
5681 /* NIP cannot be restored if the memory exception comes from an helper */
5682 gen_update_nip(ctx, ctx->nip - 4);
5683 gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
a750fc0b 5684 /* Note: Rc update flag set leads to undefined state of Rc0 */
76a66253
JM
5685#endif
5686}
5687
a750fc0b 5688/* mfdcrux (PPC 460) : user-mode access to DCR */
99e300ef 5689static void gen_mfdcrux(DisasContext *ctx)
a750fc0b 5690{
06dca6a7
AJ
5691 /* NIP cannot be restored if the memory exception comes from an helper */
5692 gen_update_nip(ctx, ctx->nip - 4);
5693 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
a750fc0b
JM
5694 /* Note: Rc update flag set leads to undefined state of Rc0 */
5695}
5696
5697/* mtdcrux (PPC 460) : user-mode access to DCR */
99e300ef 5698static void gen_mtdcrux(DisasContext *ctx)
a750fc0b 5699{
06dca6a7
AJ
5700 /* NIP cannot be restored if the memory exception comes from an helper */
5701 gen_update_nip(ctx, ctx->nip - 4);
5702 gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
a750fc0b
JM
5703 /* Note: Rc update flag set leads to undefined state of Rc0 */
5704}
5705
76a66253 5706/* dccci */
99e300ef 5707static void gen_dccci(DisasContext *ctx)
76a66253
JM
5708{
5709#if defined(CONFIG_USER_ONLY)
e06fcd75 5710 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5711#else
76db3ba4 5712 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5713 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5714 return;
5715 }
5716 /* interpreted as no-op */
5717#endif
5718}
5719
5720/* dcread */
99e300ef 5721static void gen_dcread(DisasContext *ctx)
76a66253
JM
5722{
5723#if defined(CONFIG_USER_ONLY)
e06fcd75 5724 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5725#else
b61f2753 5726 TCGv EA, val;
76db3ba4 5727 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5728 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5729 return;
5730 }
76db3ba4 5731 gen_set_access_type(ctx, ACCESS_CACHE);
a7812ae4 5732 EA = tcg_temp_new();
76db3ba4 5733 gen_addr_reg_index(ctx, EA);
a7812ae4 5734 val = tcg_temp_new();
76db3ba4 5735 gen_qemu_ld32u(ctx, val, EA);
b61f2753
AJ
5736 tcg_temp_free(val);
5737 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5738 tcg_temp_free(EA);
76a66253
JM
5739#endif
5740}
5741
5742/* icbt */
e8eaa2c0 5743static void gen_icbt_40x(DisasContext *ctx)
76a66253
JM
5744{
5745 /* interpreted as no-op */
5746 /* XXX: specification say this is treated as a load by the MMU
5747 * but does not generate any exception
5748 */
5749}
5750
5751/* iccci */
99e300ef 5752static void gen_iccci(DisasContext *ctx)
76a66253
JM
5753{
5754#if defined(CONFIG_USER_ONLY)
e06fcd75 5755 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5756#else
76db3ba4 5757 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5758 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5759 return;
5760 }
5761 /* interpreted as no-op */
5762#endif
5763}
5764
5765/* icread */
99e300ef 5766static void gen_icread(DisasContext *ctx)
76a66253
JM
5767{
5768#if defined(CONFIG_USER_ONLY)
e06fcd75 5769 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5770#else
76db3ba4 5771 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5772 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5773 return;
5774 }
5775 /* interpreted as no-op */
5776#endif
5777}
5778
76db3ba4 5779/* rfci (mem_idx only) */
e8eaa2c0 5780static void gen_rfci_40x(DisasContext *ctx)
a42bd6cc
JM
5781{
5782#if defined(CONFIG_USER_ONLY)
e06fcd75 5783 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc 5784#else
76db3ba4 5785 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5786 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc
JM
5787 return;
5788 }
5789 /* Restore CPU state */
d72a19f7 5790 gen_helper_40x_rfci();
e06fcd75 5791 gen_sync_exception(ctx);
a42bd6cc
JM
5792#endif
5793}
5794
99e300ef 5795static void gen_rfci(DisasContext *ctx)
a42bd6cc
JM
5796{
5797#if defined(CONFIG_USER_ONLY)
e06fcd75 5798 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc 5799#else
76db3ba4 5800 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5801 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc
JM
5802 return;
5803 }
5804 /* Restore CPU state */
d72a19f7 5805 gen_helper_rfci();
e06fcd75 5806 gen_sync_exception(ctx);
a42bd6cc
JM
5807#endif
5808}
5809
5810/* BookE specific */
99e300ef 5811
54623277 5812/* XXX: not implemented on 440 ? */
99e300ef 5813static void gen_rfdi(DisasContext *ctx)
76a66253
JM
5814{
5815#if defined(CONFIG_USER_ONLY)
e06fcd75 5816 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5817#else
76db3ba4 5818 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5819 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5820 return;
5821 }
5822 /* Restore CPU state */
d72a19f7 5823 gen_helper_rfdi();
e06fcd75 5824 gen_sync_exception(ctx);
76a66253
JM
5825#endif
5826}
5827
2662a059 5828/* XXX: not implemented on 440 ? */
99e300ef 5829static void gen_rfmci(DisasContext *ctx)
a42bd6cc
JM
5830{
5831#if defined(CONFIG_USER_ONLY)
e06fcd75 5832 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc 5833#else
76db3ba4 5834 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5835 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
a42bd6cc
JM
5836 return;
5837 }
5838 /* Restore CPU state */
d72a19f7 5839 gen_helper_rfmci();
e06fcd75 5840 gen_sync_exception(ctx);
a42bd6cc
JM
5841#endif
5842}
5eb7995e 5843
d9bce9d9 5844/* TLB management - PowerPC 405 implementation */
e8eaa2c0 5845
54623277 5846/* tlbre */
e8eaa2c0 5847static void gen_tlbre_40x(DisasContext *ctx)
76a66253
JM
5848{
5849#if defined(CONFIG_USER_ONLY)
e06fcd75 5850 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5851#else
76db3ba4 5852 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5853 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5854 return;
5855 }
5856 switch (rB(ctx->opcode)) {
5857 case 0:
74d37793 5858 gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5859 break;
5860 case 1:
74d37793 5861 gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5862 break;
5863 default:
e06fcd75 5864 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253 5865 break;
9a64fbe4 5866 }
76a66253
JM
5867#endif
5868}
5869
d9bce9d9 5870/* tlbsx - tlbsx. */
e8eaa2c0 5871static void gen_tlbsx_40x(DisasContext *ctx)
76a66253
JM
5872{
5873#if defined(CONFIG_USER_ONLY)
e06fcd75 5874 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5875#else
74d37793 5876 TCGv t0;
76db3ba4 5877 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5878 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5879 return;
5880 }
74d37793 5881 t0 = tcg_temp_new();
76db3ba4 5882 gen_addr_reg_index(ctx, t0);
74d37793
AJ
5883 gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5884 tcg_temp_free(t0);
5885 if (Rc(ctx->opcode)) {
5886 int l1 = gen_new_label();
5887 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5888 tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5889 tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5890 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5891 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5892 gen_set_label(l1);
5893 }
76a66253 5894#endif
79aceca5
FB
5895}
5896
76a66253 5897/* tlbwe */
e8eaa2c0 5898static void gen_tlbwe_40x(DisasContext *ctx)
79aceca5 5899{
76a66253 5900#if defined(CONFIG_USER_ONLY)
e06fcd75 5901 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 5902#else
76db3ba4 5903 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5904 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
5905 return;
5906 }
5907 switch (rB(ctx->opcode)) {
5908 case 0:
74d37793 5909 gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
5910 break;
5911 case 1:
74d37793 5912 gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
5913 break;
5914 default:
e06fcd75 5915 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
76a66253 5916 break;
9a64fbe4 5917 }
76a66253
JM
5918#endif
5919}
5920
a4bb6c3e 5921/* TLB management - PowerPC 440 implementation */
e8eaa2c0 5922
54623277 5923/* tlbre */
e8eaa2c0 5924static void gen_tlbre_440(DisasContext *ctx)
5eb7995e
JM
5925{
5926#if defined(CONFIG_USER_ONLY)
e06fcd75 5927 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e 5928#else
76db3ba4 5929 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5930 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e
JM
5931 return;
5932 }
5933 switch (rB(ctx->opcode)) {
5934 case 0:
5eb7995e 5935 case 1:
5eb7995e 5936 case 2:
74d37793
AJ
5937 {
5938 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5823947f 5939 gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], t0, cpu_gpr[rA(ctx->opcode)]);
74d37793
AJ
5940 tcg_temp_free_i32(t0);
5941 }
5eb7995e
JM
5942 break;
5943 default:
e06fcd75 5944 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5eb7995e
JM
5945 break;
5946 }
5947#endif
5948}
5949
5950/* tlbsx - tlbsx. */
e8eaa2c0 5951static void gen_tlbsx_440(DisasContext *ctx)
5eb7995e
JM
5952{
5953#if defined(CONFIG_USER_ONLY)
e06fcd75 5954 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e 5955#else
74d37793 5956 TCGv t0;
76db3ba4 5957 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5958 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e
JM
5959 return;
5960 }
74d37793 5961 t0 = tcg_temp_new();
76db3ba4 5962 gen_addr_reg_index(ctx, t0);
74d37793
AJ
5963 gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0);
5964 tcg_temp_free(t0);
5965 if (Rc(ctx->opcode)) {
5966 int l1 = gen_new_label();
5967 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
5968 tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
5969 tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
5970 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1);
5971 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02);
5972 gen_set_label(l1);
5973 }
5eb7995e
JM
5974#endif
5975}
5976
5977/* tlbwe */
e8eaa2c0 5978static void gen_tlbwe_440(DisasContext *ctx)
5eb7995e
JM
5979{
5980#if defined(CONFIG_USER_ONLY)
e06fcd75 5981 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e 5982#else
76db3ba4 5983 if (unlikely(!ctx->mem_idx)) {
e06fcd75 5984 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
5eb7995e
JM
5985 return;
5986 }
5987 switch (rB(ctx->opcode)) {
5988 case 0:
5eb7995e 5989 case 1:
5eb7995e 5990 case 2:
74d37793
AJ
5991 {
5992 TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
5993 gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
5994 tcg_temp_free_i32(t0);
5995 }
5eb7995e
JM
5996 break;
5997 default:
e06fcd75 5998 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
5eb7995e
JM
5999 break;
6000 }
6001#endif
6002}
6003
01662f3e
AG
6004/* TLB management - PowerPC BookE 2.06 implementation */
6005
6006/* tlbre */
6007static void gen_tlbre_booke206(DisasContext *ctx)
6008{
6009#if defined(CONFIG_USER_ONLY)
6010 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6011#else
6012 if (unlikely(!ctx->mem_idx)) {
6013 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6014 return;
6015 }
6016
6017 gen_helper_booke206_tlbre();
6018#endif
6019}
6020
6021/* tlbsx - tlbsx. */
6022static void gen_tlbsx_booke206(DisasContext *ctx)
6023{
6024#if defined(CONFIG_USER_ONLY)
6025 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6026#else
6027 TCGv t0;
6028 if (unlikely(!ctx->mem_idx)) {
6029 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6030 return;
6031 }
6032
6033 if (rA(ctx->opcode)) {
6034 t0 = tcg_temp_new();
6035 tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
6036 } else {
6037 t0 = tcg_const_tl(0);
6038 }
6039
6040 tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
6041 gen_helper_booke206_tlbsx(t0);
6042#endif
6043}
6044
6045/* tlbwe */
6046static void gen_tlbwe_booke206(DisasContext *ctx)
6047{
6048#if defined(CONFIG_USER_ONLY)
6049 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6050#else
6051 if (unlikely(!ctx->mem_idx)) {
6052 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6053 return;
6054 }
6055 gen_helper_booke206_tlbwe();
6056#endif
6057}
6058
6059static void gen_tlbivax_booke206(DisasContext *ctx)
6060{
6061#if defined(CONFIG_USER_ONLY)
6062 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6063#else
6064 TCGv t0;
6065 if (unlikely(!ctx->mem_idx)) {
6066 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
6067 return;
6068 }
6069
6070 t0 = tcg_temp_new();
6071 gen_addr_reg_index(ctx, t0);
6072
6073 gen_helper_booke206_tlbivax(t0);
6074#endif
6075}
6076
6077
76a66253 6078/* wrtee */
99e300ef 6079static void gen_wrtee(DisasContext *ctx)
76a66253
JM
6080{
6081#if defined(CONFIG_USER_ONLY)
e06fcd75 6082 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 6083#else
6527f6ea 6084 TCGv t0;
76db3ba4 6085 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6086 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
6087 return;
6088 }
6527f6ea
AJ
6089 t0 = tcg_temp_new();
6090 tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6091 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6092 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6093 tcg_temp_free(t0);
dee96f6c
JM
6094 /* Stop translation to have a chance to raise an exception
6095 * if we just set msr_ee to 1
6096 */
e06fcd75 6097 gen_stop_exception(ctx);
76a66253
JM
6098#endif
6099}
6100
6101/* wrteei */
99e300ef 6102static void gen_wrteei(DisasContext *ctx)
76a66253
JM
6103{
6104#if defined(CONFIG_USER_ONLY)
e06fcd75 6105 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253 6106#else
76db3ba4 6107 if (unlikely(!ctx->mem_idx)) {
e06fcd75 6108 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
76a66253
JM
6109 return;
6110 }
fbe73008 6111 if (ctx->opcode & 0x00008000) {
6527f6ea
AJ
6112 tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6113 /* Stop translation to have a chance to raise an exception */
e06fcd75 6114 gen_stop_exception(ctx);
6527f6ea 6115 } else {
1b6e5f99 6116 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6527f6ea 6117 }
76a66253
JM
6118#endif
6119}
6120
08e46e54 6121/* PowerPC 440 specific instructions */
99e300ef 6122
54623277 6123/* dlmzb */
99e300ef 6124static void gen_dlmzb(DisasContext *ctx)
76a66253 6125{
ef0d51af
AJ
6126 TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6127 gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
6128 cpu_gpr[rB(ctx->opcode)], t0);
6129 tcg_temp_free_i32(t0);
76a66253
JM
6130}
6131
6132/* mbar replaces eieio on 440 */
99e300ef 6133static void gen_mbar(DisasContext *ctx)
76a66253
JM
6134{
6135 /* interpreted as no-op */
6136}
6137
6138/* msync replaces sync on 440 */
99e300ef 6139static void gen_msync(DisasContext *ctx)
76a66253
JM
6140{
6141 /* interpreted as no-op */
6142}
6143
6144/* icbt */
e8eaa2c0 6145static void gen_icbt_440(DisasContext *ctx)
76a66253
JM
6146{
6147 /* interpreted as no-op */
6148 /* XXX: specification say this is treated as a load by the MMU
6149 * but does not generate any exception
6150 */
79aceca5
FB
6151}
6152
a9d9eb8f
JM
6153/*** Altivec vector extension ***/
6154/* Altivec registers moves */
a9d9eb8f 6155
636aa200 6156static inline TCGv_ptr gen_avr_ptr(int reg)
564e571a 6157{
e4704b3b 6158 TCGv_ptr r = tcg_temp_new_ptr();
564e571a
AJ
6159 tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
6160 return r;
6161}
6162
a9d9eb8f 6163#define GEN_VR_LDX(name, opc2, opc3) \
99e300ef 6164static void glue(gen_, name)(DisasContext *ctx) \
a9d9eb8f 6165{ \
fe1e5c53 6166 TCGv EA; \
a9d9eb8f 6167 if (unlikely(!ctx->altivec_enabled)) { \
e06fcd75 6168 gen_exception(ctx, POWERPC_EXCP_VPU); \
a9d9eb8f
JM
6169 return; \
6170 } \
76db3ba4 6171 gen_set_access_type(ctx, ACCESS_INT); \
fe1e5c53 6172 EA = tcg_temp_new(); \
76db3ba4 6173 gen_addr_reg_index(ctx, EA); \
fe1e5c53 6174 tcg_gen_andi_tl(EA, EA, ~0xf); \
76db3ba4
AJ
6175 if (ctx->le_mode) { \
6176 gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53 6177 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6178 gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6179 } else { \
76db3ba4 6180 gen_qemu_ld64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6181 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6182 gen_qemu_ld64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53
AJ
6183 } \
6184 tcg_temp_free(EA); \
a9d9eb8f
JM
6185}
6186
6187#define GEN_VR_STX(name, opc2, opc3) \
99e300ef 6188static void gen_st##name(DisasContext *ctx) \
a9d9eb8f 6189{ \
fe1e5c53 6190 TCGv EA; \
a9d9eb8f 6191 if (unlikely(!ctx->altivec_enabled)) { \
e06fcd75 6192 gen_exception(ctx, POWERPC_EXCP_VPU); \
a9d9eb8f
JM
6193 return; \
6194 } \
76db3ba4 6195 gen_set_access_type(ctx, ACCESS_INT); \
fe1e5c53 6196 EA = tcg_temp_new(); \
76db3ba4 6197 gen_addr_reg_index(ctx, EA); \
fe1e5c53 6198 tcg_gen_andi_tl(EA, EA, ~0xf); \
76db3ba4
AJ
6199 if (ctx->le_mode) { \
6200 gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53 6201 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6202 gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6203 } else { \
76db3ba4 6204 gen_qemu_st64(ctx, cpu_avrh[rD(ctx->opcode)], EA); \
fe1e5c53 6205 tcg_gen_addi_tl(EA, EA, 8); \
76db3ba4 6206 gen_qemu_st64(ctx, cpu_avrl[rD(ctx->opcode)], EA); \
fe1e5c53
AJ
6207 } \
6208 tcg_temp_free(EA); \
a9d9eb8f
JM
6209}
6210
cbfb6ae9 6211#define GEN_VR_LVE(name, opc2, opc3) \
99e300ef 6212static void gen_lve##name(DisasContext *ctx) \
cbfb6ae9
AJ
6213 { \
6214 TCGv EA; \
6215 TCGv_ptr rs; \
6216 if (unlikely(!ctx->altivec_enabled)) { \
6217 gen_exception(ctx, POWERPC_EXCP_VPU); \
6218 return; \
6219 } \
6220 gen_set_access_type(ctx, ACCESS_INT); \
6221 EA = tcg_temp_new(); \
6222 gen_addr_reg_index(ctx, EA); \
6223 rs = gen_avr_ptr(rS(ctx->opcode)); \
6224 gen_helper_lve##name (rs, EA); \
6225 tcg_temp_free(EA); \
6226 tcg_temp_free_ptr(rs); \
6227 }
6228
6229#define GEN_VR_STVE(name, opc2, opc3) \
99e300ef 6230static void gen_stve##name(DisasContext *ctx) \
cbfb6ae9
AJ
6231 { \
6232 TCGv EA; \
6233 TCGv_ptr rs; \
6234 if (unlikely(!ctx->altivec_enabled)) { \
6235 gen_exception(ctx, POWERPC_EXCP_VPU); \
6236 return; \
6237 } \
6238 gen_set_access_type(ctx, ACCESS_INT); \
6239 EA = tcg_temp_new(); \
6240 gen_addr_reg_index(ctx, EA); \
6241 rs = gen_avr_ptr(rS(ctx->opcode)); \
6242 gen_helper_stve##name (rs, EA); \
6243 tcg_temp_free(EA); \
6244 tcg_temp_free_ptr(rs); \
6245 }
6246
fe1e5c53 6247GEN_VR_LDX(lvx, 0x07, 0x03);
a9d9eb8f 6248/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
fe1e5c53 6249GEN_VR_LDX(lvxl, 0x07, 0x0B);
a9d9eb8f 6250
cbfb6ae9
AJ
6251GEN_VR_LVE(bx, 0x07, 0x00);
6252GEN_VR_LVE(hx, 0x07, 0x01);
6253GEN_VR_LVE(wx, 0x07, 0x02);
6254
fe1e5c53 6255GEN_VR_STX(svx, 0x07, 0x07);
a9d9eb8f 6256/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
fe1e5c53 6257GEN_VR_STX(svxl, 0x07, 0x0F);
a9d9eb8f 6258
cbfb6ae9
AJ
6259GEN_VR_STVE(bx, 0x07, 0x04);
6260GEN_VR_STVE(hx, 0x07, 0x05);
6261GEN_VR_STVE(wx, 0x07, 0x06);
6262
99e300ef 6263static void gen_lvsl(DisasContext *ctx)
bf8d8ded
AJ
6264{
6265 TCGv_ptr rd;
6266 TCGv EA;
6267 if (unlikely(!ctx->altivec_enabled)) {
6268 gen_exception(ctx, POWERPC_EXCP_VPU);
6269 return;
6270 }
6271 EA = tcg_temp_new();
6272 gen_addr_reg_index(ctx, EA);
6273 rd = gen_avr_ptr(rD(ctx->opcode));
6274 gen_helper_lvsl(rd, EA);
6275 tcg_temp_free(EA);
6276 tcg_temp_free_ptr(rd);
6277}
6278
99e300ef 6279static void gen_lvsr(DisasContext *ctx)
bf8d8ded
AJ
6280{
6281 TCGv_ptr rd;
6282 TCGv EA;
6283 if (unlikely(!ctx->altivec_enabled)) {
6284 gen_exception(ctx, POWERPC_EXCP_VPU);
6285 return;
6286 }
6287 EA = tcg_temp_new();
6288 gen_addr_reg_index(ctx, EA);
6289 rd = gen_avr_ptr(rD(ctx->opcode));
6290 gen_helper_lvsr(rd, EA);
6291 tcg_temp_free(EA);
6292 tcg_temp_free_ptr(rd);
6293}
6294
99e300ef 6295static void gen_mfvscr(DisasContext *ctx)
785f451b
AJ
6296{
6297 TCGv_i32 t;
6298 if (unlikely(!ctx->altivec_enabled)) {
6299 gen_exception(ctx, POWERPC_EXCP_VPU);
6300 return;
6301 }
6302 tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
6303 t = tcg_temp_new_i32();
6304 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, vscr));
6305 tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
fce5ecb7 6306 tcg_temp_free_i32(t);
785f451b
AJ
6307}
6308
99e300ef 6309static void gen_mtvscr(DisasContext *ctx)
785f451b 6310{
6e87b7c7 6311 TCGv_ptr p;
785f451b
AJ
6312 if (unlikely(!ctx->altivec_enabled)) {
6313 gen_exception(ctx, POWERPC_EXCP_VPU);
6314 return;
6315 }
6e87b7c7
AJ
6316 p = gen_avr_ptr(rD(ctx->opcode));
6317 gen_helper_mtvscr(p);
6318 tcg_temp_free_ptr(p);
785f451b
AJ
6319}
6320
7a9b96cf
AJ
6321/* Logical operations */
6322#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
99e300ef 6323static void glue(gen_, name)(DisasContext *ctx) \
7a9b96cf
AJ
6324{ \
6325 if (unlikely(!ctx->altivec_enabled)) { \
6326 gen_exception(ctx, POWERPC_EXCP_VPU); \
6327 return; \
6328 } \
6329 tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
6330 tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
6331}
6332
6333GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
6334GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
6335GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
6336GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
6337GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
6338
8e27dd6f 6339#define GEN_VXFORM(name, opc2, opc3) \
99e300ef 6340static void glue(gen_, name)(DisasContext *ctx) \
8e27dd6f
AJ
6341{ \
6342 TCGv_ptr ra, rb, rd; \
6343 if (unlikely(!ctx->altivec_enabled)) { \
6344 gen_exception(ctx, POWERPC_EXCP_VPU); \
6345 return; \
6346 } \
6347 ra = gen_avr_ptr(rA(ctx->opcode)); \
6348 rb = gen_avr_ptr(rB(ctx->opcode)); \
6349 rd = gen_avr_ptr(rD(ctx->opcode)); \
6350 gen_helper_##name (rd, ra, rb); \
6351 tcg_temp_free_ptr(ra); \
6352 tcg_temp_free_ptr(rb); \
6353 tcg_temp_free_ptr(rd); \
6354}
6355
7872c51c
AJ
6356GEN_VXFORM(vaddubm, 0, 0);
6357GEN_VXFORM(vadduhm, 0, 1);
6358GEN_VXFORM(vadduwm, 0, 2);
6359GEN_VXFORM(vsububm, 0, 16);
6360GEN_VXFORM(vsubuhm, 0, 17);
6361GEN_VXFORM(vsubuwm, 0, 18);
e4039339
AJ
6362GEN_VXFORM(vmaxub, 1, 0);
6363GEN_VXFORM(vmaxuh, 1, 1);
6364GEN_VXFORM(vmaxuw, 1, 2);
6365GEN_VXFORM(vmaxsb, 1, 4);
6366GEN_VXFORM(vmaxsh, 1, 5);
6367GEN_VXFORM(vmaxsw, 1, 6);
6368GEN_VXFORM(vminub, 1, 8);
6369GEN_VXFORM(vminuh, 1, 9);
6370GEN_VXFORM(vminuw, 1, 10);
6371GEN_VXFORM(vminsb, 1, 12);
6372GEN_VXFORM(vminsh, 1, 13);
6373GEN_VXFORM(vminsw, 1, 14);
fab3cbe9
AJ
6374GEN_VXFORM(vavgub, 1, 16);
6375GEN_VXFORM(vavguh, 1, 17);
6376GEN_VXFORM(vavguw, 1, 18);
6377GEN_VXFORM(vavgsb, 1, 20);
6378GEN_VXFORM(vavgsh, 1, 21);
6379GEN_VXFORM(vavgsw, 1, 22);
3b430048
AJ
6380GEN_VXFORM(vmrghb, 6, 0);
6381GEN_VXFORM(vmrghh, 6, 1);
6382GEN_VXFORM(vmrghw, 6, 2);
6383GEN_VXFORM(vmrglb, 6, 4);
6384GEN_VXFORM(vmrglh, 6, 5);
6385GEN_VXFORM(vmrglw, 6, 6);
2c277908
AJ
6386GEN_VXFORM(vmuloub, 4, 0);
6387GEN_VXFORM(vmulouh, 4, 1);
6388GEN_VXFORM(vmulosb, 4, 4);
6389GEN_VXFORM(vmulosh, 4, 5);
6390GEN_VXFORM(vmuleub, 4, 8);
6391GEN_VXFORM(vmuleuh, 4, 9);
6392GEN_VXFORM(vmulesb, 4, 12);
6393GEN_VXFORM(vmulesh, 4, 13);
d79f0809
AJ
6394GEN_VXFORM(vslb, 2, 4);
6395GEN_VXFORM(vslh, 2, 5);
6396GEN_VXFORM(vslw, 2, 6);
07ef34c3
AJ
6397GEN_VXFORM(vsrb, 2, 8);
6398GEN_VXFORM(vsrh, 2, 9);
6399GEN_VXFORM(vsrw, 2, 10);
6400GEN_VXFORM(vsrab, 2, 12);
6401GEN_VXFORM(vsrah, 2, 13);
6402GEN_VXFORM(vsraw, 2, 14);
7b239bec
AJ
6403GEN_VXFORM(vslo, 6, 16);
6404GEN_VXFORM(vsro, 6, 17);
e343da72
AJ
6405GEN_VXFORM(vaddcuw, 0, 6);
6406GEN_VXFORM(vsubcuw, 0, 22);
5ab09f33
AJ
6407GEN_VXFORM(vaddubs, 0, 8);
6408GEN_VXFORM(vadduhs, 0, 9);
6409GEN_VXFORM(vadduws, 0, 10);
6410GEN_VXFORM(vaddsbs, 0, 12);
6411GEN_VXFORM(vaddshs, 0, 13);
6412GEN_VXFORM(vaddsws, 0, 14);
6413GEN_VXFORM(vsububs, 0, 24);
6414GEN_VXFORM(vsubuhs, 0, 25);
6415GEN_VXFORM(vsubuws, 0, 26);
6416GEN_VXFORM(vsubsbs, 0, 28);
6417GEN_VXFORM(vsubshs, 0, 29);
6418GEN_VXFORM(vsubsws, 0, 30);
5e1d0985
AJ
6419GEN_VXFORM(vrlb, 2, 0);
6420GEN_VXFORM(vrlh, 2, 1);
6421GEN_VXFORM(vrlw, 2, 2);
d9430add
AJ
6422GEN_VXFORM(vsl, 2, 7);
6423GEN_VXFORM(vsr, 2, 11);
5335a145
AJ
6424GEN_VXFORM(vpkuhum, 7, 0);
6425GEN_VXFORM(vpkuwum, 7, 1);
6426GEN_VXFORM(vpkuhus, 7, 2);
6427GEN_VXFORM(vpkuwus, 7, 3);
6428GEN_VXFORM(vpkshus, 7, 4);
6429GEN_VXFORM(vpkswus, 7, 5);
6430GEN_VXFORM(vpkshss, 7, 6);
6431GEN_VXFORM(vpkswss, 7, 7);
1dd9ffb9 6432GEN_VXFORM(vpkpx, 7, 12);
8142cddd
AJ
6433GEN_VXFORM(vsum4ubs, 4, 24);
6434GEN_VXFORM(vsum4sbs, 4, 28);
6435GEN_VXFORM(vsum4shs, 4, 25);
6436GEN_VXFORM(vsum2sws, 4, 26);
6437GEN_VXFORM(vsumsws, 4, 30);
56fdd213
AJ
6438GEN_VXFORM(vaddfp, 5, 0);
6439GEN_VXFORM(vsubfp, 5, 1);
1536ff64
AJ
6440GEN_VXFORM(vmaxfp, 5, 16);
6441GEN_VXFORM(vminfp, 5, 17);
fab3cbe9 6442
0cbcd906 6443#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
e8eaa2c0 6444static void glue(gen_, name)(DisasContext *ctx) \
0cbcd906
AJ
6445 { \
6446 TCGv_ptr ra, rb, rd; \
6447 if (unlikely(!ctx->altivec_enabled)) { \
6448 gen_exception(ctx, POWERPC_EXCP_VPU); \
6449 return; \
6450 } \
6451 ra = gen_avr_ptr(rA(ctx->opcode)); \
6452 rb = gen_avr_ptr(rB(ctx->opcode)); \
6453 rd = gen_avr_ptr(rD(ctx->opcode)); \
6454 gen_helper_##opname (rd, ra, rb); \
6455 tcg_temp_free_ptr(ra); \
6456 tcg_temp_free_ptr(rb); \
6457 tcg_temp_free_ptr(rd); \
6458 }
6459
6460#define GEN_VXRFORM(name, opc2, opc3) \
6461 GEN_VXRFORM1(name, name, #name, opc2, opc3) \
6462 GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
6463
1add6e23
AJ
6464GEN_VXRFORM(vcmpequb, 3, 0)
6465GEN_VXRFORM(vcmpequh, 3, 1)
6466GEN_VXRFORM(vcmpequw, 3, 2)
6467GEN_VXRFORM(vcmpgtsb, 3, 12)
6468GEN_VXRFORM(vcmpgtsh, 3, 13)
6469GEN_VXRFORM(vcmpgtsw, 3, 14)
6470GEN_VXRFORM(vcmpgtub, 3, 8)
6471GEN_VXRFORM(vcmpgtuh, 3, 9)
6472GEN_VXRFORM(vcmpgtuw, 3, 10)
819ca121
AJ
6473GEN_VXRFORM(vcmpeqfp, 3, 3)
6474GEN_VXRFORM(vcmpgefp, 3, 7)
6475GEN_VXRFORM(vcmpgtfp, 3, 11)
6476GEN_VXRFORM(vcmpbfp, 3, 15)
1add6e23 6477
c026766b 6478#define GEN_VXFORM_SIMM(name, opc2, opc3) \
99e300ef 6479static void glue(gen_, name)(DisasContext *ctx) \
c026766b
AJ
6480 { \
6481 TCGv_ptr rd; \
6482 TCGv_i32 simm; \
6483 if (unlikely(!ctx->altivec_enabled)) { \
6484 gen_exception(ctx, POWERPC_EXCP_VPU); \
6485 return; \
6486 } \
6487 simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6488 rd = gen_avr_ptr(rD(ctx->opcode)); \
6489 gen_helper_##name (rd, simm); \
6490 tcg_temp_free_i32(simm); \
6491 tcg_temp_free_ptr(rd); \
6492 }
6493
6494GEN_VXFORM_SIMM(vspltisb, 6, 12);
6495GEN_VXFORM_SIMM(vspltish, 6, 13);
6496GEN_VXFORM_SIMM(vspltisw, 6, 14);
6497
de5f2484 6498#define GEN_VXFORM_NOA(name, opc2, opc3) \
99e300ef 6499static void glue(gen_, name)(DisasContext *ctx) \
de5f2484
AJ
6500 { \
6501 TCGv_ptr rb, rd; \
6502 if (unlikely(!ctx->altivec_enabled)) { \
6503 gen_exception(ctx, POWERPC_EXCP_VPU); \
6504 return; \
6505 } \
6506 rb = gen_avr_ptr(rB(ctx->opcode)); \
6507 rd = gen_avr_ptr(rD(ctx->opcode)); \
6508 gen_helper_##name (rd, rb); \
6509 tcg_temp_free_ptr(rb); \
6510 tcg_temp_free_ptr(rd); \
6511 }
6512
6cf1c6e5
AJ
6513GEN_VXFORM_NOA(vupkhsb, 7, 8);
6514GEN_VXFORM_NOA(vupkhsh, 7, 9);
6515GEN_VXFORM_NOA(vupklsb, 7, 10);
6516GEN_VXFORM_NOA(vupklsh, 7, 11);
79f85c3a
AJ
6517GEN_VXFORM_NOA(vupkhpx, 7, 13);
6518GEN_VXFORM_NOA(vupklpx, 7, 15);
bdfbac35 6519GEN_VXFORM_NOA(vrefp, 5, 4);
071fc3b1 6520GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
0bffbc6c 6521GEN_VXFORM_NOA(vexptefp, 5, 6);
b580763f 6522GEN_VXFORM_NOA(vlogefp, 5, 7);
f6b19645
AJ
6523GEN_VXFORM_NOA(vrfim, 5, 8);
6524GEN_VXFORM_NOA(vrfin, 5, 9);
6525GEN_VXFORM_NOA(vrfip, 5, 10);
6526GEN_VXFORM_NOA(vrfiz, 5, 11);
79f85c3a 6527
21d21583 6528#define GEN_VXFORM_SIMM(name, opc2, opc3) \
99e300ef 6529static void glue(gen_, name)(DisasContext *ctx) \
21d21583
AJ
6530 { \
6531 TCGv_ptr rd; \
6532 TCGv_i32 simm; \
6533 if (unlikely(!ctx->altivec_enabled)) { \
6534 gen_exception(ctx, POWERPC_EXCP_VPU); \
6535 return; \
6536 } \
6537 simm = tcg_const_i32(SIMM5(ctx->opcode)); \
6538 rd = gen_avr_ptr(rD(ctx->opcode)); \
6539 gen_helper_##name (rd, simm); \
6540 tcg_temp_free_i32(simm); \
6541 tcg_temp_free_ptr(rd); \
6542 }
6543
27a4edb3 6544#define GEN_VXFORM_UIMM(name, opc2, opc3) \
99e300ef 6545static void glue(gen_, name)(DisasContext *ctx) \
27a4edb3
AJ
6546 { \
6547 TCGv_ptr rb, rd; \
6548 TCGv_i32 uimm; \
6549 if (unlikely(!ctx->altivec_enabled)) { \
6550 gen_exception(ctx, POWERPC_EXCP_VPU); \
6551 return; \
6552 } \
6553 uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
6554 rb = gen_avr_ptr(rB(ctx->opcode)); \
6555 rd = gen_avr_ptr(rD(ctx->opcode)); \
6556 gen_helper_##name (rd, rb, uimm); \
6557 tcg_temp_free_i32(uimm); \
6558 tcg_temp_free_ptr(rb); \
6559 tcg_temp_free_ptr(rd); \
6560 }
6561
e4e6bee7
AJ
6562GEN_VXFORM_UIMM(vspltb, 6, 8);
6563GEN_VXFORM_UIMM(vsplth, 6, 9);
6564GEN_VXFORM_UIMM(vspltw, 6, 10);
e140632e
AJ
6565GEN_VXFORM_UIMM(vcfux, 5, 12);
6566GEN_VXFORM_UIMM(vcfsx, 5, 13);
875b31db
AJ
6567GEN_VXFORM_UIMM(vctuxs, 5, 14);
6568GEN_VXFORM_UIMM(vctsxs, 5, 15);
e4e6bee7 6569
99e300ef 6570static void gen_vsldoi(DisasContext *ctx)
cd633b10
AJ
6571{
6572 TCGv_ptr ra, rb, rd;
fce5ecb7 6573 TCGv_i32 sh;
cd633b10
AJ
6574 if (unlikely(!ctx->altivec_enabled)) {
6575 gen_exception(ctx, POWERPC_EXCP_VPU);
6576 return;
6577 }
6578 ra = gen_avr_ptr(rA(ctx->opcode));
6579 rb = gen_avr_ptr(rB(ctx->opcode));
6580 rd = gen_avr_ptr(rD(ctx->opcode));
6581 sh = tcg_const_i32(VSH(ctx->opcode));
6582 gen_helper_vsldoi (rd, ra, rb, sh);
6583 tcg_temp_free_ptr(ra);
6584 tcg_temp_free_ptr(rb);
6585 tcg_temp_free_ptr(rd);
fce5ecb7 6586 tcg_temp_free_i32(sh);
cd633b10
AJ
6587}
6588
707cec33 6589#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
99e300ef 6590static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
707cec33
AJ
6591 { \
6592 TCGv_ptr ra, rb, rc, rd; \
6593 if (unlikely(!ctx->altivec_enabled)) { \
6594 gen_exception(ctx, POWERPC_EXCP_VPU); \
6595 return; \
6596 } \
6597 ra = gen_avr_ptr(rA(ctx->opcode)); \
6598 rb = gen_avr_ptr(rB(ctx->opcode)); \
6599 rc = gen_avr_ptr(rC(ctx->opcode)); \
6600 rd = gen_avr_ptr(rD(ctx->opcode)); \
6601 if (Rc(ctx->opcode)) { \
6602 gen_helper_##name1 (rd, ra, rb, rc); \
6603 } else { \
6604 gen_helper_##name0 (rd, ra, rb, rc); \
6605 } \
6606 tcg_temp_free_ptr(ra); \
6607 tcg_temp_free_ptr(rb); \
6608 tcg_temp_free_ptr(rc); \
6609 tcg_temp_free_ptr(rd); \
6610 }
6611
b161ae27
AJ
6612GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
6613
99e300ef 6614static void gen_vmladduhm(DisasContext *ctx)
bcd2ee23
AJ
6615{
6616 TCGv_ptr ra, rb, rc, rd;
6617 if (unlikely(!ctx->altivec_enabled)) {
6618 gen_exception(ctx, POWERPC_EXCP_VPU);
6619 return;
6620 }
6621 ra = gen_avr_ptr(rA(ctx->opcode));
6622 rb = gen_avr_ptr(rB(ctx->opcode));
6623 rc = gen_avr_ptr(rC(ctx->opcode));
6624 rd = gen_avr_ptr(rD(ctx->opcode));
6625 gen_helper_vmladduhm(rd, ra, rb, rc);
6626 tcg_temp_free_ptr(ra);
6627 tcg_temp_free_ptr(rb);
6628 tcg_temp_free_ptr(rc);
6629 tcg_temp_free_ptr(rd);
6630}
6631
b04ae981 6632GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
4d9903b6 6633GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
eae07261 6634GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
d1258698 6635GEN_VAFORM_PAIRED(vsel, vperm, 21)
35cf7c7e 6636GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
b04ae981 6637
0487d6a8 6638/*** SPE extension ***/
0487d6a8 6639/* Register moves */
3cd7d1dd 6640
a0e13900
FC
6641
6642static inline void gen_evmra(DisasContext *ctx)
6643{
6644
6645 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 6646 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
6647 return;
6648 }
6649
6650#if defined(TARGET_PPC64)
6651 /* rD := rA */
6652 tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6653
6654 /* spe_acc := rA */
6655 tcg_gen_st_i64(cpu_gpr[rA(ctx->opcode)],
6656 cpu_env,
6657 offsetof(CPUState, spe_acc));
6658#else
6659 TCGv_i64 tmp = tcg_temp_new_i64();
6660
6661 /* tmp := rA_lo + rA_hi << 32 */
6662 tcg_gen_concat_i32_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6663
6664 /* spe_acc := tmp */
6665 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
6666 tcg_temp_free_i64(tmp);
6667
6668 /* rD := rA */
6669 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6670 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6671#endif
6672}
6673
636aa200
BS
6674static inline void gen_load_gpr64(TCGv_i64 t, int reg)
6675{
f78fb44e
AJ
6676#if defined(TARGET_PPC64)
6677 tcg_gen_mov_i64(t, cpu_gpr[reg]);
6678#else
36aa55dc 6679 tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
3cd7d1dd 6680#endif
f78fb44e 6681}
3cd7d1dd 6682
636aa200
BS
6683static inline void gen_store_gpr64(int reg, TCGv_i64 t)
6684{
f78fb44e
AJ
6685#if defined(TARGET_PPC64)
6686 tcg_gen_mov_i64(cpu_gpr[reg], t);
6687#else
a7812ae4 6688 TCGv_i64 tmp = tcg_temp_new_i64();
f78fb44e 6689 tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
f78fb44e
AJ
6690 tcg_gen_shri_i64(tmp, t, 32);
6691 tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
a7812ae4 6692 tcg_temp_free_i64(tmp);
3cd7d1dd 6693#endif
f78fb44e 6694}
3cd7d1dd 6695
0487d6a8 6696#define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
99e300ef 6697static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
0487d6a8
JM
6698{ \
6699 if (Rc(ctx->opcode)) \
6700 gen_##name1(ctx); \
6701 else \
6702 gen_##name0(ctx); \
6703}
6704
6705/* Handler for undefined SPE opcodes */
636aa200 6706static inline void gen_speundef(DisasContext *ctx)
0487d6a8 6707{
e06fcd75 6708 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
0487d6a8
JM
6709}
6710
57951c27
AJ
6711/* SPE logic */
6712#if defined(TARGET_PPC64)
6713#define GEN_SPEOP_LOGIC2(name, tcg_op) \
636aa200 6714static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
6715{ \
6716 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 6717 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
6718 return; \
6719 } \
57951c27
AJ
6720 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6721 cpu_gpr[rB(ctx->opcode)]); \
6722}
6723#else
6724#define GEN_SPEOP_LOGIC2(name, tcg_op) \
636aa200 6725static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
6726{ \
6727 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 6728 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
6729 return; \
6730 } \
6731 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6732 cpu_gpr[rB(ctx->opcode)]); \
6733 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6734 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 6735}
57951c27
AJ
6736#endif
6737
6738GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6739GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6740GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6741GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6742GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6743GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6744GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6745GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
0487d6a8 6746
57951c27
AJ
6747/* SPE logic immediate */
6748#if defined(TARGET_PPC64)
6749#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
636aa200 6750static inline void gen_##name(DisasContext *ctx) \
3d3a6a0a
AJ
6751{ \
6752 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 6753 gen_exception(ctx, POWERPC_EXCP_SPEU); \
3d3a6a0a
AJ
6754 return; \
6755 } \
a7812ae4
PB
6756 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6757 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6758 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6759 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6760 tcg_opi(t0, t0, rB(ctx->opcode)); \
6761 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6762 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6763 tcg_temp_free_i64(t2); \
57951c27
AJ
6764 tcg_opi(t1, t1, rB(ctx->opcode)); \
6765 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6766 tcg_temp_free_i32(t0); \
6767 tcg_temp_free_i32(t1); \
3d3a6a0a 6768}
57951c27
AJ
6769#else
6770#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
636aa200 6771static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
6772{ \
6773 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 6774 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
6775 return; \
6776 } \
57951c27
AJ
6777 tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6778 rB(ctx->opcode)); \
6779 tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6780 rB(ctx->opcode)); \
0487d6a8 6781}
57951c27
AJ
6782#endif
6783GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
6784GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
6785GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
6786GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
0487d6a8 6787
57951c27
AJ
6788/* SPE arithmetic */
6789#if defined(TARGET_PPC64)
6790#define GEN_SPEOP_ARITH1(name, tcg_op) \
636aa200 6791static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
6792{ \
6793 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 6794 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
6795 return; \
6796 } \
a7812ae4
PB
6797 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6798 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6799 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6800 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6801 tcg_op(t0, t0); \
6802 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6803 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6804 tcg_temp_free_i64(t2); \
57951c27
AJ
6805 tcg_op(t1, t1); \
6806 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6807 tcg_temp_free_i32(t0); \
6808 tcg_temp_free_i32(t1); \
0487d6a8 6809}
57951c27 6810#else
a7812ae4 6811#define GEN_SPEOP_ARITH1(name, tcg_op) \
636aa200 6812static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
6813{ \
6814 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 6815 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
6816 return; \
6817 } \
6818 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
6819 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
6820}
6821#endif
0487d6a8 6822
636aa200 6823static inline void gen_op_evabs(TCGv_i32 ret, TCGv_i32 arg1)
57951c27
AJ
6824{
6825 int l1 = gen_new_label();
6826 int l2 = gen_new_label();
0487d6a8 6827
57951c27
AJ
6828 tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6829 tcg_gen_neg_i32(ret, arg1);
6830 tcg_gen_br(l2);
6831 gen_set_label(l1);
a7812ae4 6832 tcg_gen_mov_i32(ret, arg1);
57951c27
AJ
6833 gen_set_label(l2);
6834}
6835GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6836GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6837GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6838GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
636aa200 6839static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1)
0487d6a8 6840{
57951c27
AJ
6841 tcg_gen_addi_i32(ret, arg1, 0x8000);
6842 tcg_gen_ext16u_i32(ret, ret);
6843}
6844GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
a7812ae4
PB
6845GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6846GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
0487d6a8 6847
57951c27
AJ
6848#if defined(TARGET_PPC64)
6849#define GEN_SPEOP_ARITH2(name, tcg_op) \
636aa200 6850static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
6851{ \
6852 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 6853 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
6854 return; \
6855 } \
a7812ae4
PB
6856 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6857 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6858 TCGv_i32 t2 = tcg_temp_local_new_i32(); \
501e23c4 6859 TCGv_i64 t3 = tcg_temp_local_new_i64(); \
57951c27
AJ
6860 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6861 tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
6862 tcg_op(t0, t0, t2); \
6863 tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
6864 tcg_gen_trunc_i64_i32(t1, t3); \
6865 tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
6866 tcg_gen_trunc_i64_i32(t2, t3); \
a7812ae4 6867 tcg_temp_free_i64(t3); \
57951c27 6868 tcg_op(t1, t1, t2); \
a7812ae4 6869 tcg_temp_free_i32(t2); \
57951c27 6870 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6871 tcg_temp_free_i32(t0); \
6872 tcg_temp_free_i32(t1); \
0487d6a8 6873}
57951c27
AJ
6874#else
6875#define GEN_SPEOP_ARITH2(name, tcg_op) \
636aa200 6876static inline void gen_##name(DisasContext *ctx) \
0487d6a8
JM
6877{ \
6878 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 6879 gen_exception(ctx, POWERPC_EXCP_SPEU); \
0487d6a8
JM
6880 return; \
6881 } \
57951c27
AJ
6882 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6883 cpu_gpr[rB(ctx->opcode)]); \
6884 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6885 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 6886}
57951c27 6887#endif
0487d6a8 6888
636aa200 6889static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6890{
a7812ae4 6891 TCGv_i32 t0;
57951c27 6892 int l1, l2;
0487d6a8 6893
57951c27
AJ
6894 l1 = gen_new_label();
6895 l2 = gen_new_label();
a7812ae4 6896 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6897 /* No error here: 6 bits are used */
6898 tcg_gen_andi_i32(t0, arg2, 0x3F);
6899 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6900 tcg_gen_shr_i32(ret, arg1, t0);
6901 tcg_gen_br(l2);
6902 gen_set_label(l1);
6903 tcg_gen_movi_i32(ret, 0);
0aef4261 6904 gen_set_label(l2);
a7812ae4 6905 tcg_temp_free_i32(t0);
57951c27
AJ
6906}
6907GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
636aa200 6908static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6909{
a7812ae4 6910 TCGv_i32 t0;
57951c27
AJ
6911 int l1, l2;
6912
6913 l1 = gen_new_label();
6914 l2 = gen_new_label();
a7812ae4 6915 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6916 /* No error here: 6 bits are used */
6917 tcg_gen_andi_i32(t0, arg2, 0x3F);
6918 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6919 tcg_gen_sar_i32(ret, arg1, t0);
6920 tcg_gen_br(l2);
6921 gen_set_label(l1);
6922 tcg_gen_movi_i32(ret, 0);
0aef4261 6923 gen_set_label(l2);
a7812ae4 6924 tcg_temp_free_i32(t0);
57951c27
AJ
6925}
6926GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
636aa200 6927static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6928{
a7812ae4 6929 TCGv_i32 t0;
57951c27
AJ
6930 int l1, l2;
6931
6932 l1 = gen_new_label();
6933 l2 = gen_new_label();
a7812ae4 6934 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6935 /* No error here: 6 bits are used */
6936 tcg_gen_andi_i32(t0, arg2, 0x3F);
6937 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6938 tcg_gen_shl_i32(ret, arg1, t0);
6939 tcg_gen_br(l2);
6940 gen_set_label(l1);
6941 tcg_gen_movi_i32(ret, 0);
e29ef9fa 6942 gen_set_label(l2);
a7812ae4 6943 tcg_temp_free_i32(t0);
57951c27
AJ
6944}
6945GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
636aa200 6946static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6947{
a7812ae4 6948 TCGv_i32 t0 = tcg_temp_new_i32();
57951c27
AJ
6949 tcg_gen_andi_i32(t0, arg2, 0x1F);
6950 tcg_gen_rotl_i32(ret, arg1, t0);
a7812ae4 6951 tcg_temp_free_i32(t0);
57951c27
AJ
6952}
6953GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
636aa200 6954static inline void gen_evmergehi(DisasContext *ctx)
57951c27
AJ
6955{
6956 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 6957 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
6958 return;
6959 }
6960#if defined(TARGET_PPC64)
a7812ae4
PB
6961 TCGv t0 = tcg_temp_new();
6962 TCGv t1 = tcg_temp_new();
57951c27
AJ
6963 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6964 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6965 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6966 tcg_temp_free(t0);
6967 tcg_temp_free(t1);
6968#else
6969 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6970 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6971#endif
6972}
6973GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
636aa200 6974static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
0487d6a8 6975{
57951c27
AJ
6976 tcg_gen_sub_i32(ret, arg2, arg1);
6977}
6978GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
0487d6a8 6979
57951c27
AJ
6980/* SPE arithmetic immediate */
6981#if defined(TARGET_PPC64)
6982#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
636aa200 6983static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
6984{ \
6985 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 6986 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
6987 return; \
6988 } \
a7812ae4
PB
6989 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6990 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6991 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6992 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
6993 tcg_op(t0, t0, rA(ctx->opcode)); \
6994 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6995 tcg_gen_trunc_i64_i32(t1, t2); \
e06fcd75 6996 tcg_temp_free_i64(t2); \
57951c27
AJ
6997 tcg_op(t1, t1, rA(ctx->opcode)); \
6998 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6999 tcg_temp_free_i32(t0); \
7000 tcg_temp_free_i32(t1); \
57951c27
AJ
7001}
7002#else
7003#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
636aa200 7004static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7005{ \
7006 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7007 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7008 return; \
7009 } \
7010 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
7011 rA(ctx->opcode)); \
7012 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
7013 rA(ctx->opcode)); \
7014}
7015#endif
7016GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
7017GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
7018
7019/* SPE comparison */
7020#if defined(TARGET_PPC64)
7021#define GEN_SPEOP_COMP(name, tcg_cond) \
636aa200 7022static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7023{ \
7024 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7025 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7026 return; \
7027 } \
7028 int l1 = gen_new_label(); \
7029 int l2 = gen_new_label(); \
7030 int l3 = gen_new_label(); \
7031 int l4 = gen_new_label(); \
a7812ae4
PB
7032 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
7033 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
7034 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
7035 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7036 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7037 tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
a7812ae4 7038 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
57951c27
AJ
7039 tcg_gen_br(l2); \
7040 gen_set_label(l1); \
7041 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
7042 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
7043 gen_set_label(l2); \
7044 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
7045 tcg_gen_trunc_i64_i32(t0, t2); \
7046 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
7047 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 7048 tcg_temp_free_i64(t2); \
57951c27
AJ
7049 tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
7050 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7051 ~(CRF_CH | CRF_CH_AND_CL)); \
7052 tcg_gen_br(l4); \
7053 gen_set_label(l3); \
7054 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7055 CRF_CH | CRF_CH_OR_CL); \
7056 gen_set_label(l4); \
a7812ae4
PB
7057 tcg_temp_free_i32(t0); \
7058 tcg_temp_free_i32(t1); \
57951c27
AJ
7059}
7060#else
7061#define GEN_SPEOP_COMP(name, tcg_cond) \
636aa200 7062static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7063{ \
7064 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7065 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7066 return; \
7067 } \
7068 int l1 = gen_new_label(); \
7069 int l2 = gen_new_label(); \
7070 int l3 = gen_new_label(); \
7071 int l4 = gen_new_label(); \
7072 \
7073 tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
7074 cpu_gpr[rB(ctx->opcode)], l1); \
7075 tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
7076 tcg_gen_br(l2); \
7077 gen_set_label(l1); \
7078 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
7079 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
7080 gen_set_label(l2); \
7081 tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
7082 cpu_gprh[rB(ctx->opcode)], l3); \
7083 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7084 ~(CRF_CH | CRF_CH_AND_CL)); \
7085 tcg_gen_br(l4); \
7086 gen_set_label(l3); \
7087 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
7088 CRF_CH | CRF_CH_OR_CL); \
7089 gen_set_label(l4); \
7090}
7091#endif
7092GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
7093GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
7094GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
7095GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
7096GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
7097
7098/* SPE misc */
636aa200 7099static inline void gen_brinc(DisasContext *ctx)
57951c27
AJ
7100{
7101 /* Note: brinc is usable even if SPE is disabled */
a7812ae4
PB
7102 gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
7103 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
0487d6a8 7104}
636aa200 7105static inline void gen_evmergelo(DisasContext *ctx)
57951c27
AJ
7106{
7107 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7108 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
7109 return;
7110 }
7111#if defined(TARGET_PPC64)
a7812ae4
PB
7112 TCGv t0 = tcg_temp_new();
7113 TCGv t1 = tcg_temp_new();
17d9b3af 7114 tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
57951c27
AJ
7115 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
7116 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7117 tcg_temp_free(t0);
7118 tcg_temp_free(t1);
7119#else
57951c27 7120 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
33890b3e 7121 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
57951c27
AJ
7122#endif
7123}
636aa200 7124static inline void gen_evmergehilo(DisasContext *ctx)
57951c27
AJ
7125{
7126 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7127 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
7128 return;
7129 }
7130#if defined(TARGET_PPC64)
a7812ae4
PB
7131 TCGv t0 = tcg_temp_new();
7132 TCGv t1 = tcg_temp_new();
17d9b3af 7133 tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
57951c27
AJ
7134 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
7135 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7136 tcg_temp_free(t0);
7137 tcg_temp_free(t1);
7138#else
7139 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7140 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7141#endif
7142}
636aa200 7143static inline void gen_evmergelohi(DisasContext *ctx)
57951c27
AJ
7144{
7145 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7146 gen_exception(ctx, POWERPC_EXCP_SPEU);
57951c27
AJ
7147 return;
7148 }
7149#if defined(TARGET_PPC64)
a7812ae4
PB
7150 TCGv t0 = tcg_temp_new();
7151 TCGv t1 = tcg_temp_new();
57951c27
AJ
7152 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
7153 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
7154 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
7155 tcg_temp_free(t0);
7156 tcg_temp_free(t1);
7157#else
33890b3e
NF
7158 if (rD(ctx->opcode) == rA(ctx->opcode)) {
7159 TCGv_i32 tmp = tcg_temp_new_i32();
7160 tcg_gen_mov_i32(tmp, cpu_gpr[rA(ctx->opcode)]);
7161 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7162 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], tmp);
7163 tcg_temp_free_i32(tmp);
7164 } else {
7165 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7166 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7167 }
57951c27
AJ
7168#endif
7169}
636aa200 7170static inline void gen_evsplati(DisasContext *ctx)
57951c27 7171{
ae01847f 7172 uint64_t imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27;
0487d6a8 7173
57951c27 7174#if defined(TARGET_PPC64)
38d14952 7175 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
7176#else
7177 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7178 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7179#endif
7180}
636aa200 7181static inline void gen_evsplatfi(DisasContext *ctx)
0487d6a8 7182{
ae01847f 7183 uint64_t imm = rA(ctx->opcode) << 27;
0487d6a8 7184
57951c27 7185#if defined(TARGET_PPC64)
38d14952 7186 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
7187#else
7188 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
7189 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
7190#endif
0487d6a8
JM
7191}
7192
636aa200 7193static inline void gen_evsel(DisasContext *ctx)
57951c27
AJ
7194{
7195 int l1 = gen_new_label();
7196 int l2 = gen_new_label();
7197 int l3 = gen_new_label();
7198 int l4 = gen_new_label();
a7812ae4 7199 TCGv_i32 t0 = tcg_temp_local_new_i32();
57951c27 7200#if defined(TARGET_PPC64)
a7812ae4
PB
7201 TCGv t1 = tcg_temp_local_new();
7202 TCGv t2 = tcg_temp_local_new();
57951c27
AJ
7203#endif
7204 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
7205 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
7206#if defined(TARGET_PPC64)
7207 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7208#else
7209 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
7210#endif
7211 tcg_gen_br(l2);
7212 gen_set_label(l1);
7213#if defined(TARGET_PPC64)
7214 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
7215#else
7216 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
7217#endif
7218 gen_set_label(l2);
7219 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
7220 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
7221#if defined(TARGET_PPC64)
17d9b3af 7222 tcg_gen_ext32u_tl(t2, cpu_gpr[rA(ctx->opcode)]);
57951c27
AJ
7223#else
7224 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
7225#endif
7226 tcg_gen_br(l4);
7227 gen_set_label(l3);
7228#if defined(TARGET_PPC64)
17d9b3af 7229 tcg_gen_ext32u_tl(t2, cpu_gpr[rB(ctx->opcode)]);
57951c27
AJ
7230#else
7231 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
7232#endif
7233 gen_set_label(l4);
a7812ae4 7234 tcg_temp_free_i32(t0);
57951c27
AJ
7235#if defined(TARGET_PPC64)
7236 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
7237 tcg_temp_free(t1);
7238 tcg_temp_free(t2);
7239#endif
7240}
e8eaa2c0
BS
7241
7242static void gen_evsel0(DisasContext *ctx)
57951c27
AJ
7243{
7244 gen_evsel(ctx);
7245}
e8eaa2c0
BS
7246
7247static void gen_evsel1(DisasContext *ctx)
57951c27
AJ
7248{
7249 gen_evsel(ctx);
7250}
e8eaa2c0
BS
7251
7252static void gen_evsel2(DisasContext *ctx)
57951c27
AJ
7253{
7254 gen_evsel(ctx);
7255}
e8eaa2c0
BS
7256
7257static void gen_evsel3(DisasContext *ctx)
57951c27
AJ
7258{
7259 gen_evsel(ctx);
7260}
0487d6a8 7261
a0e13900
FC
7262/* Multiply */
7263
7264static inline void gen_evmwumi(DisasContext *ctx)
7265{
7266 TCGv_i64 t0, t1;
7267
7268 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7269 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
7270 return;
7271 }
7272
7273 t0 = tcg_temp_new_i64();
7274 t1 = tcg_temp_new_i64();
7275
7276 /* t0 := rA; t1 := rB */
7277#if defined(TARGET_PPC64)
7278 tcg_gen_ext32u_tl(t0, cpu_gpr[rA(ctx->opcode)]);
7279 tcg_gen_ext32u_tl(t1, cpu_gpr[rB(ctx->opcode)]);
7280#else
7281 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
7282 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
7283#endif
7284
7285 tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
7286
7287 gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
7288
7289 tcg_temp_free_i64(t0);
7290 tcg_temp_free_i64(t1);
7291}
7292
7293static inline void gen_evmwumia(DisasContext *ctx)
7294{
7295 TCGv_i64 tmp;
7296
7297 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7298 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
7299 return;
7300 }
7301
7302 gen_evmwumi(ctx); /* rD := rA * rB */
7303
7304 tmp = tcg_temp_new_i64();
7305
7306 /* acc := rD */
7307 gen_load_gpr64(tmp, rD(ctx->opcode));
7308 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
7309 tcg_temp_free_i64(tmp);
7310}
7311
7312static inline void gen_evmwumiaa(DisasContext *ctx)
7313{
7314 TCGv_i64 acc;
7315 TCGv_i64 tmp;
7316
7317 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7318 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
7319 return;
7320 }
7321
7322 gen_evmwumi(ctx); /* rD := rA * rB */
7323
7324 acc = tcg_temp_new_i64();
7325 tmp = tcg_temp_new_i64();
7326
7327 /* tmp := rD */
7328 gen_load_gpr64(tmp, rD(ctx->opcode));
7329
7330 /* Load acc */
7331 tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
7332
7333 /* acc := tmp + acc */
7334 tcg_gen_add_i64(acc, acc, tmp);
7335
7336 /* Store acc */
7337 tcg_gen_st_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
7338
7339 /* rD := acc */
7340 gen_store_gpr64(rD(ctx->opcode), acc);
7341
7342 tcg_temp_free_i64(acc);
7343 tcg_temp_free_i64(tmp);
7344}
7345
7346static inline void gen_evmwsmi(DisasContext *ctx)
7347{
7348 TCGv_i64 t0, t1;
7349
7350 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 7351 gen_exception(ctx, POWERPC_EXCP_SPEU);
a0e13900
FC
7352 return;
7353 }
7354
7355 t0 = tcg_temp_new_i64();
7356 t1 = tcg_temp_new_i64();
7357
7358 /* t0 := rA; t1 := rB */
7359#if defined(TARGET_PPC64)
7360 tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
7361 tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
7362#else
7363 tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
7364 tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
7365#endif
7366
7367 tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
7368
7369 gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
7370
7371 tcg_temp_free_i64(t0);
7372 tcg_temp_free_i64(t1);
7373}
7374
7375static inline void gen_evmwsmia(DisasContext *ctx)
7376{
7377 TCGv_i64 tmp;
7378
7379 gen_evmwsmi(ctx); /* rD := rA * rB */
7380
7381 tmp = tcg_temp_new_i64();
7382
7383 /* acc := rD */
7384 gen_load_gpr64(tmp, rD(ctx->opcode));
7385 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, spe_acc));
7386
7387 tcg_temp_free_i64(tmp);
7388}
7389
7390static inline void gen_evmwsmiaa(DisasContext *ctx)
7391{
7392 TCGv_i64 acc = tcg_temp_new_i64();
7393 TCGv_i64 tmp = tcg_temp_new_i64();
7394
7395 gen_evmwsmi(ctx); /* rD := rA * rB */
7396
7397 acc = tcg_temp_new_i64();
7398 tmp = tcg_temp_new_i64();
7399
7400 /* tmp := rD */
7401 gen_load_gpr64(tmp, rD(ctx->opcode));
7402
7403 /* Load acc */
7404 tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
7405
7406 /* acc := tmp + acc */
7407 tcg_gen_add_i64(acc, acc, tmp);
7408
7409 /* Store acc */
7410 tcg_gen_st_i64(acc, cpu_env, offsetof(CPUState, spe_acc));
7411
7412 /* rD := acc */
7413 gen_store_gpr64(rD(ctx->opcode), acc);
7414
7415 tcg_temp_free_i64(acc);
7416 tcg_temp_free_i64(tmp);
7417}
7418
0487d6a8
JM
7419GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
7420GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
7421GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
7422GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
7423GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
7424GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
7425GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
7426GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
a0e13900 7427GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, PPC_SPE);
0487d6a8
JM
7428GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
7429GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
7430GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
7431GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
a0e13900
FC
7432GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
7433GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
7434GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
0487d6a8
JM
7435GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
7436GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
7437GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
7438GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
7439GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
7440GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
7441GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
7442GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
7443GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
7444GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
7445GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
7446GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
7447GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
7448
6a6ae23f 7449/* SPE load and stores */
636aa200 7450static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
6a6ae23f
AJ
7451{
7452 target_ulong uimm = rB(ctx->opcode);
7453
76db3ba4 7454 if (rA(ctx->opcode) == 0) {
6a6ae23f 7455 tcg_gen_movi_tl(EA, uimm << sh);
76db3ba4 7456 } else {
6a6ae23f 7457 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
76db3ba4
AJ
7458#if defined(TARGET_PPC64)
7459 if (!ctx->sf_mode) {
7460 tcg_gen_ext32u_tl(EA, EA);
7461 }
7462#endif
7463 }
0487d6a8 7464}
6a6ae23f 7465
636aa200 7466static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7467{
7468#if defined(TARGET_PPC64)
76db3ba4 7469 gen_qemu_ld64(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f
AJ
7470#else
7471 TCGv_i64 t0 = tcg_temp_new_i64();
76db3ba4 7472 gen_qemu_ld64(ctx, t0, addr);
6a6ae23f
AJ
7473 tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
7474 tcg_gen_shri_i64(t0, t0, 32);
7475 tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
7476 tcg_temp_free_i64(t0);
7477#endif
0487d6a8 7478}
6a6ae23f 7479
636aa200 7480static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
6a6ae23f 7481{
0487d6a8 7482#if defined(TARGET_PPC64)
6a6ae23f 7483 TCGv t0 = tcg_temp_new();
76db3ba4 7484 gen_qemu_ld32u(ctx, t0, addr);
6a6ae23f 7485 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
76db3ba4
AJ
7486 gen_addr_add(ctx, addr, addr, 4);
7487 gen_qemu_ld32u(ctx, t0, addr);
6a6ae23f
AJ
7488 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7489 tcg_temp_free(t0);
7490#else
76db3ba4
AJ
7491 gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7492 gen_addr_add(ctx, addr, addr, 4);
7493 gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f 7494#endif
0487d6a8 7495}
6a6ae23f 7496
636aa200 7497static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7498{
7499 TCGv t0 = tcg_temp_new();
7500#if defined(TARGET_PPC64)
76db3ba4 7501 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 7502 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
76db3ba4
AJ
7503 gen_addr_add(ctx, addr, addr, 2);
7504 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7505 tcg_gen_shli_tl(t0, t0, 32);
7506 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
76db3ba4
AJ
7507 gen_addr_add(ctx, addr, addr, 2);
7508 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7509 tcg_gen_shli_tl(t0, t0, 16);
7510 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
76db3ba4
AJ
7511 gen_addr_add(ctx, addr, addr, 2);
7512 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 7513 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 7514#else
76db3ba4 7515 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 7516 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
76db3ba4
AJ
7517 gen_addr_add(ctx, addr, addr, 2);
7518 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 7519 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
76db3ba4
AJ
7520 gen_addr_add(ctx, addr, addr, 2);
7521 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 7522 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
76db3ba4
AJ
7523 gen_addr_add(ctx, addr, addr, 2);
7524 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 7525 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 7526#endif
6a6ae23f 7527 tcg_temp_free(t0);
0487d6a8
JM
7528}
7529
636aa200 7530static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7531{
7532 TCGv t0 = tcg_temp_new();
76db3ba4 7533 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7534#if defined(TARGET_PPC64)
7535 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7536 tcg_gen_shli_tl(t0, t0, 16);
7537 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7538#else
7539 tcg_gen_shli_tl(t0, t0, 16);
7540 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7541 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7542#endif
7543 tcg_temp_free(t0);
0487d6a8
JM
7544}
7545
636aa200 7546static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7547{
7548 TCGv t0 = tcg_temp_new();
76db3ba4 7549 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7550#if defined(TARGET_PPC64)
7551 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7552 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7553#else
7554 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7555 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7556#endif
7557 tcg_temp_free(t0);
0487d6a8
JM
7558}
7559
636aa200 7560static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7561{
7562 TCGv t0 = tcg_temp_new();
76db3ba4 7563 gen_qemu_ld16s(ctx, t0, addr);
6a6ae23f
AJ
7564#if defined(TARGET_PPC64)
7565 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7566 tcg_gen_ext32u_tl(t0, t0);
7567 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7568#else
7569 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7570 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7571#endif
7572 tcg_temp_free(t0);
7573}
7574
636aa200 7575static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7576{
7577 TCGv t0 = tcg_temp_new();
7578#if defined(TARGET_PPC64)
76db3ba4 7579 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 7580 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
76db3ba4
AJ
7581 gen_addr_add(ctx, addr, addr, 2);
7582 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7583 tcg_gen_shli_tl(t0, t0, 16);
7584 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7585#else
76db3ba4 7586 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f 7587 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
76db3ba4
AJ
7588 gen_addr_add(ctx, addr, addr, 2);
7589 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7590 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7591#endif
7592 tcg_temp_free(t0);
7593}
7594
636aa200 7595static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7596{
7597#if defined(TARGET_PPC64)
7598 TCGv t0 = tcg_temp_new();
76db3ba4
AJ
7599 gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
7600 gen_addr_add(ctx, addr, addr, 2);
7601 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7602 tcg_gen_shli_tl(t0, t0, 32);
7603 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7604 tcg_temp_free(t0);
7605#else
76db3ba4
AJ
7606 gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7607 gen_addr_add(ctx, addr, addr, 2);
7608 gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f
AJ
7609#endif
7610}
7611
636aa200 7612static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7613{
7614#if defined(TARGET_PPC64)
7615 TCGv t0 = tcg_temp_new();
76db3ba4 7616 gen_qemu_ld16s(ctx, t0, addr);
6a6ae23f 7617 tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
76db3ba4
AJ
7618 gen_addr_add(ctx, addr, addr, 2);
7619 gen_qemu_ld16s(ctx, t0, addr);
6a6ae23f
AJ
7620 tcg_gen_shli_tl(t0, t0, 32);
7621 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7622 tcg_temp_free(t0);
7623#else
76db3ba4
AJ
7624 gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr);
7625 gen_addr_add(ctx, addr, addr, 2);
7626 gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr);
6a6ae23f
AJ
7627#endif
7628}
7629
636aa200 7630static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7631{
7632 TCGv t0 = tcg_temp_new();
76db3ba4 7633 gen_qemu_ld32u(ctx, t0, addr);
0487d6a8 7634#if defined(TARGET_PPC64)
6a6ae23f
AJ
7635 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
7636 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7637#else
7638 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
7639 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
7640#endif
7641 tcg_temp_free(t0);
7642}
7643
636aa200 7644static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7645{
7646 TCGv t0 = tcg_temp_new();
7647#if defined(TARGET_PPC64)
76db3ba4 7648 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7649 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
7650 tcg_gen_shli_tl(t0, t0, 32);
7651 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
76db3ba4
AJ
7652 gen_addr_add(ctx, addr, addr, 2);
7653 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7654 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7655 tcg_gen_shli_tl(t0, t0, 16);
7656 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
7657#else
76db3ba4 7658 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7659 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
7660 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
76db3ba4
AJ
7661 gen_addr_add(ctx, addr, addr, 2);
7662 gen_qemu_ld16u(ctx, t0, addr);
6a6ae23f
AJ
7663 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
7664 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
0487d6a8 7665#endif
6a6ae23f
AJ
7666 tcg_temp_free(t0);
7667}
7668
636aa200 7669static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7670{
7671#if defined(TARGET_PPC64)
76db3ba4 7672 gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], addr);
0487d6a8 7673#else
6a6ae23f
AJ
7674 TCGv_i64 t0 = tcg_temp_new_i64();
7675 tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
76db3ba4 7676 gen_qemu_st64(ctx, t0, addr);
6a6ae23f
AJ
7677 tcg_temp_free_i64(t0);
7678#endif
7679}
7680
636aa200 7681static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
6a6ae23f 7682{
0487d6a8 7683#if defined(TARGET_PPC64)
6a6ae23f
AJ
7684 TCGv t0 = tcg_temp_new();
7685 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
76db3ba4 7686 gen_qemu_st32(ctx, t0, addr);
6a6ae23f
AJ
7687 tcg_temp_free(t0);
7688#else
76db3ba4 7689 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6a6ae23f 7690#endif
76db3ba4
AJ
7691 gen_addr_add(ctx, addr, addr, 4);
7692 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
7693}
7694
636aa200 7695static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7696{
7697 TCGv t0 = tcg_temp_new();
7698#if defined(TARGET_PPC64)
7699 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7700#else
7701 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7702#endif
76db3ba4
AJ
7703 gen_qemu_st16(ctx, t0, addr);
7704 gen_addr_add(ctx, addr, addr, 2);
6a6ae23f
AJ
7705#if defined(TARGET_PPC64)
7706 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
76db3ba4 7707 gen_qemu_st16(ctx, t0, addr);
6a6ae23f 7708#else
76db3ba4 7709 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6a6ae23f 7710#endif
76db3ba4 7711 gen_addr_add(ctx, addr, addr, 2);
6a6ae23f 7712 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
76db3ba4 7713 gen_qemu_st16(ctx, t0, addr);
6a6ae23f 7714 tcg_temp_free(t0);
76db3ba4
AJ
7715 gen_addr_add(ctx, addr, addr, 2);
7716 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
7717}
7718
636aa200 7719static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7720{
7721 TCGv t0 = tcg_temp_new();
7722#if defined(TARGET_PPC64)
7723 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
7724#else
7725 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
7726#endif
76db3ba4
AJ
7727 gen_qemu_st16(ctx, t0, addr);
7728 gen_addr_add(ctx, addr, addr, 2);
6a6ae23f 7729 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
76db3ba4 7730 gen_qemu_st16(ctx, t0, addr);
6a6ae23f
AJ
7731 tcg_temp_free(t0);
7732}
7733
636aa200 7734static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7735{
7736#if defined(TARGET_PPC64)
7737 TCGv t0 = tcg_temp_new();
7738 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
76db3ba4 7739 gen_qemu_st16(ctx, t0, addr);
6a6ae23f
AJ
7740 tcg_temp_free(t0);
7741#else
76db3ba4 7742 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6a6ae23f 7743#endif
76db3ba4
AJ
7744 gen_addr_add(ctx, addr, addr, 2);
7745 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
7746}
7747
636aa200 7748static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
6a6ae23f
AJ
7749{
7750#if defined(TARGET_PPC64)
7751 TCGv t0 = tcg_temp_new();
7752 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
76db3ba4 7753 gen_qemu_st32(ctx, t0, addr);
6a6ae23f
AJ
7754 tcg_temp_free(t0);
7755#else
76db3ba4 7756 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr);
6a6ae23f
AJ
7757#endif
7758}
7759
636aa200 7760static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
6a6ae23f 7761{
76db3ba4 7762 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr);
6a6ae23f
AJ
7763}
7764
7765#define GEN_SPEOP_LDST(name, opc2, sh) \
99e300ef 7766static void glue(gen_, name)(DisasContext *ctx) \
6a6ae23f
AJ
7767{ \
7768 TCGv t0; \
7769 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7770 gen_exception(ctx, POWERPC_EXCP_SPEU); \
6a6ae23f
AJ
7771 return; \
7772 } \
76db3ba4 7773 gen_set_access_type(ctx, ACCESS_INT); \
6a6ae23f
AJ
7774 t0 = tcg_temp_new(); \
7775 if (Rc(ctx->opcode)) { \
76db3ba4 7776 gen_addr_spe_imm_index(ctx, t0, sh); \
6a6ae23f 7777 } else { \
76db3ba4 7778 gen_addr_reg_index(ctx, t0); \
6a6ae23f
AJ
7779 } \
7780 gen_op_##name(ctx, t0); \
7781 tcg_temp_free(t0); \
7782}
7783
7784GEN_SPEOP_LDST(evldd, 0x00, 3);
7785GEN_SPEOP_LDST(evldw, 0x01, 3);
7786GEN_SPEOP_LDST(evldh, 0x02, 3);
7787GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
7788GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
7789GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
7790GEN_SPEOP_LDST(evlwhe, 0x08, 2);
7791GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
7792GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
7793GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
7794GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
7795
7796GEN_SPEOP_LDST(evstdd, 0x10, 3);
7797GEN_SPEOP_LDST(evstdw, 0x11, 3);
7798GEN_SPEOP_LDST(evstdh, 0x12, 3);
7799GEN_SPEOP_LDST(evstwhe, 0x18, 2);
7800GEN_SPEOP_LDST(evstwho, 0x1A, 2);
7801GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
7802GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
0487d6a8
JM
7803
7804/* Multiply and add - TODO */
7805#if 0
7806GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
7807GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
7808GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
7809GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
7810GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
7811GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
7812GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
7813GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
7814GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
7815GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
7816GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
7817GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
7818
7819GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
7820GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
7821GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
7822GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
7823GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
0487d6a8
JM
7824GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
7825GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
7826GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
7827GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
7828GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
7829GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
0487d6a8
JM
7830GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
7831
7832GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
7833GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
7834GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
7835GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
7836GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
0487d6a8
JM
7837
7838GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
7839GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
7840GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
7841GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
7842GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
7843GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
7844GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
7845GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
7846GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
7847GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
7848GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
7849GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
7850
7851GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
7852GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
7853GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
0487d6a8
JM
7854GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
7855
7856GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
7857GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
7858GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
7859GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
7860GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
7861GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
7862GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
7863GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
7864GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
7865GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
7866GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
7867GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
7868
7869GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
7870GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
7871GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
7872GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
7873GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
7874#endif
7875
7876/*** SPE floating-point extension ***/
1c97856d
AJ
7877#if defined(TARGET_PPC64)
7878#define GEN_SPEFPUOP_CONV_32_32(name) \
636aa200 7879static inline void gen_##name(DisasContext *ctx) \
0487d6a8 7880{ \
1c97856d
AJ
7881 TCGv_i32 t0; \
7882 TCGv t1; \
7883 t0 = tcg_temp_new_i32(); \
7884 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7885 gen_helper_##name(t0, t0); \
7886 t1 = tcg_temp_new(); \
7887 tcg_gen_extu_i32_tl(t1, t0); \
7888 tcg_temp_free_i32(t0); \
7889 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7890 0xFFFFFFFF00000000ULL); \
7891 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7892 tcg_temp_free(t1); \
0487d6a8 7893}
1c97856d 7894#define GEN_SPEFPUOP_CONV_32_64(name) \
636aa200 7895static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
7896{ \
7897 TCGv_i32 t0; \
7898 TCGv t1; \
7899 t0 = tcg_temp_new_i32(); \
7900 gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7901 t1 = tcg_temp_new(); \
7902 tcg_gen_extu_i32_tl(t1, t0); \
7903 tcg_temp_free_i32(t0); \
7904 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7905 0xFFFFFFFF00000000ULL); \
7906 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7907 tcg_temp_free(t1); \
7908}
7909#define GEN_SPEFPUOP_CONV_64_32(name) \
636aa200 7910static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
7911{ \
7912 TCGv_i32 t0 = tcg_temp_new_i32(); \
7913 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7914 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7915 tcg_temp_free_i32(t0); \
7916}
7917#define GEN_SPEFPUOP_CONV_64_64(name) \
636aa200 7918static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
7919{ \
7920 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7921}
7922#define GEN_SPEFPUOP_ARITH2_32_32(name) \
636aa200 7923static inline void gen_##name(DisasContext *ctx) \
57951c27 7924{ \
1c97856d
AJ
7925 TCGv_i32 t0, t1; \
7926 TCGv_i64 t2; \
57951c27 7927 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7928 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7929 return; \
7930 } \
1c97856d
AJ
7931 t0 = tcg_temp_new_i32(); \
7932 t1 = tcg_temp_new_i32(); \
7933 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7934 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7935 gen_helper_##name(t0, t0, t1); \
7936 tcg_temp_free_i32(t1); \
7937 t2 = tcg_temp_new(); \
7938 tcg_gen_extu_i32_tl(t2, t0); \
7939 tcg_temp_free_i32(t0); \
7940 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7941 0xFFFFFFFF00000000ULL); \
7942 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2); \
7943 tcg_temp_free(t2); \
57951c27 7944}
1c97856d 7945#define GEN_SPEFPUOP_ARITH2_64_64(name) \
636aa200 7946static inline void gen_##name(DisasContext *ctx) \
57951c27
AJ
7947{ \
7948 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7949 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7950 return; \
7951 } \
1c97856d
AJ
7952 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7953 cpu_gpr[rB(ctx->opcode)]); \
57951c27 7954}
1c97856d 7955#define GEN_SPEFPUOP_COMP_32(name) \
636aa200 7956static inline void gen_##name(DisasContext *ctx) \
57951c27 7957{ \
1c97856d 7958 TCGv_i32 t0, t1; \
57951c27 7959 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7960 gen_exception(ctx, POWERPC_EXCP_SPEU); \
57951c27
AJ
7961 return; \
7962 } \
1c97856d
AJ
7963 t0 = tcg_temp_new_i32(); \
7964 t1 = tcg_temp_new_i32(); \
7965 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7966 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7967 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7968 tcg_temp_free_i32(t0); \
7969 tcg_temp_free_i32(t1); \
7970}
7971#define GEN_SPEFPUOP_COMP_64(name) \
636aa200 7972static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
7973{ \
7974 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 7975 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
7976 return; \
7977 } \
7978 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7979 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7980}
7981#else
7982#define GEN_SPEFPUOP_CONV_32_32(name) \
636aa200 7983static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
7984{ \
7985 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
57951c27 7986}
1c97856d 7987#define GEN_SPEFPUOP_CONV_32_64(name) \
636aa200 7988static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
7989{ \
7990 TCGv_i64 t0 = tcg_temp_new_i64(); \
7991 gen_load_gpr64(t0, rB(ctx->opcode)); \
7992 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7993 tcg_temp_free_i64(t0); \
7994}
7995#define GEN_SPEFPUOP_CONV_64_32(name) \
636aa200 7996static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
7997{ \
7998 TCGv_i64 t0 = tcg_temp_new_i64(); \
7999 gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
8000 gen_store_gpr64(rD(ctx->opcode), t0); \
8001 tcg_temp_free_i64(t0); \
8002}
8003#define GEN_SPEFPUOP_CONV_64_64(name) \
636aa200 8004static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8005{ \
8006 TCGv_i64 t0 = tcg_temp_new_i64(); \
8007 gen_load_gpr64(t0, rB(ctx->opcode)); \
8008 gen_helper_##name(t0, t0); \
8009 gen_store_gpr64(rD(ctx->opcode), t0); \
8010 tcg_temp_free_i64(t0); \
8011}
8012#define GEN_SPEFPUOP_ARITH2_32_32(name) \
636aa200 8013static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8014{ \
8015 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8016 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
8017 return; \
8018 } \
8019 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], \
8020 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8021}
8022#define GEN_SPEFPUOP_ARITH2_64_64(name) \
636aa200 8023static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8024{ \
8025 TCGv_i64 t0, t1; \
8026 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8027 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
8028 return; \
8029 } \
8030 t0 = tcg_temp_new_i64(); \
8031 t1 = tcg_temp_new_i64(); \
8032 gen_load_gpr64(t0, rA(ctx->opcode)); \
8033 gen_load_gpr64(t1, rB(ctx->opcode)); \
8034 gen_helper_##name(t0, t0, t1); \
8035 gen_store_gpr64(rD(ctx->opcode), t0); \
8036 tcg_temp_free_i64(t0); \
8037 tcg_temp_free_i64(t1); \
8038}
8039#define GEN_SPEFPUOP_COMP_32(name) \
636aa200 8040static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8041{ \
8042 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8043 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
8044 return; \
8045 } \
8046 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
8047 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
8048}
8049#define GEN_SPEFPUOP_COMP_64(name) \
636aa200 8050static inline void gen_##name(DisasContext *ctx) \
1c97856d
AJ
8051{ \
8052 TCGv_i64 t0, t1; \
8053 if (unlikely(!ctx->spe_enabled)) { \
27a69bb0 8054 gen_exception(ctx, POWERPC_EXCP_SPEU); \
1c97856d
AJ
8055 return; \
8056 } \
8057 t0 = tcg_temp_new_i64(); \
8058 t1 = tcg_temp_new_i64(); \
8059 gen_load_gpr64(t0, rA(ctx->opcode)); \
8060 gen_load_gpr64(t1, rB(ctx->opcode)); \
8061 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
8062 tcg_temp_free_i64(t0); \
8063 tcg_temp_free_i64(t1); \
8064}
8065#endif
57951c27 8066
0487d6a8
JM
8067/* Single precision floating-point vectors operations */
8068/* Arithmetic */
1c97856d
AJ
8069GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
8070GEN_SPEFPUOP_ARITH2_64_64(evfssub);
8071GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
8072GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
636aa200 8073static inline void gen_evfsabs(DisasContext *ctx)
1c97856d
AJ
8074{
8075 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8076 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8077 return;
8078 }
8079#if defined(TARGET_PPC64)
6d5c34fa 8080 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
1c97856d 8081#else
6d5c34fa
MP
8082 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
8083 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
1c97856d
AJ
8084#endif
8085}
636aa200 8086static inline void gen_evfsnabs(DisasContext *ctx)
1c97856d
AJ
8087{
8088 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8089 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8090 return;
8091 }
8092#if defined(TARGET_PPC64)
6d5c34fa 8093 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
1c97856d 8094#else
6d5c34fa
MP
8095 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
8096 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8097#endif
8098}
636aa200 8099static inline void gen_evfsneg(DisasContext *ctx)
1c97856d
AJ
8100{
8101 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8102 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8103 return;
8104 }
8105#if defined(TARGET_PPC64)
6d5c34fa 8106 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
1c97856d 8107#else
6d5c34fa
MP
8108 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
8109 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8110#endif
8111}
8112
0487d6a8 8113/* Conversion */
1c97856d
AJ
8114GEN_SPEFPUOP_CONV_64_64(evfscfui);
8115GEN_SPEFPUOP_CONV_64_64(evfscfsi);
8116GEN_SPEFPUOP_CONV_64_64(evfscfuf);
8117GEN_SPEFPUOP_CONV_64_64(evfscfsf);
8118GEN_SPEFPUOP_CONV_64_64(evfsctui);
8119GEN_SPEFPUOP_CONV_64_64(evfsctsi);
8120GEN_SPEFPUOP_CONV_64_64(evfsctuf);
8121GEN_SPEFPUOP_CONV_64_64(evfsctsf);
8122GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
8123GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
8124
0487d6a8 8125/* Comparison */
1c97856d
AJ
8126GEN_SPEFPUOP_COMP_64(evfscmpgt);
8127GEN_SPEFPUOP_COMP_64(evfscmplt);
8128GEN_SPEFPUOP_COMP_64(evfscmpeq);
8129GEN_SPEFPUOP_COMP_64(evfststgt);
8130GEN_SPEFPUOP_COMP_64(evfststlt);
8131GEN_SPEFPUOP_COMP_64(evfststeq);
0487d6a8
JM
8132
8133/* Opcodes definitions */
40569b7e
AJ
8134GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
8135GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
8136GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
8137GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
8138GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
8139GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
8140GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
8141GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
8142GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
8143GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
8144GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
8145GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
8146GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
8147GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
0487d6a8
JM
8148
8149/* Single precision floating-point operations */
8150/* Arithmetic */
1c97856d
AJ
8151GEN_SPEFPUOP_ARITH2_32_32(efsadd);
8152GEN_SPEFPUOP_ARITH2_32_32(efssub);
8153GEN_SPEFPUOP_ARITH2_32_32(efsmul);
8154GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
636aa200 8155static inline void gen_efsabs(DisasContext *ctx)
1c97856d
AJ
8156{
8157 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8158 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8159 return;
8160 }
6d5c34fa 8161 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
1c97856d 8162}
636aa200 8163static inline void gen_efsnabs(DisasContext *ctx)
1c97856d
AJ
8164{
8165 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8166 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8167 return;
8168 }
6d5c34fa 8169 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1c97856d 8170}
636aa200 8171static inline void gen_efsneg(DisasContext *ctx)
1c97856d
AJ
8172{
8173 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8174 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8175 return;
8176 }
6d5c34fa 8177 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8178}
8179
0487d6a8 8180/* Conversion */
1c97856d
AJ
8181GEN_SPEFPUOP_CONV_32_32(efscfui);
8182GEN_SPEFPUOP_CONV_32_32(efscfsi);
8183GEN_SPEFPUOP_CONV_32_32(efscfuf);
8184GEN_SPEFPUOP_CONV_32_32(efscfsf);
8185GEN_SPEFPUOP_CONV_32_32(efsctui);
8186GEN_SPEFPUOP_CONV_32_32(efsctsi);
8187GEN_SPEFPUOP_CONV_32_32(efsctuf);
8188GEN_SPEFPUOP_CONV_32_32(efsctsf);
8189GEN_SPEFPUOP_CONV_32_32(efsctuiz);
8190GEN_SPEFPUOP_CONV_32_32(efsctsiz);
8191GEN_SPEFPUOP_CONV_32_64(efscfd);
8192
0487d6a8 8193/* Comparison */
1c97856d
AJ
8194GEN_SPEFPUOP_COMP_32(efscmpgt);
8195GEN_SPEFPUOP_COMP_32(efscmplt);
8196GEN_SPEFPUOP_COMP_32(efscmpeq);
8197GEN_SPEFPUOP_COMP_32(efststgt);
8198GEN_SPEFPUOP_COMP_32(efststlt);
8199GEN_SPEFPUOP_COMP_32(efststeq);
0487d6a8
JM
8200
8201/* Opcodes definitions */
40569b7e
AJ
8202GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
8203GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
8204GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
8205GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
8206GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
8207GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
8208GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
8209GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
8210GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
8211GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
8212GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
8213GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
8214GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
8215GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
0487d6a8
JM
8216
8217/* Double precision floating-point operations */
8218/* Arithmetic */
1c97856d
AJ
8219GEN_SPEFPUOP_ARITH2_64_64(efdadd);
8220GEN_SPEFPUOP_ARITH2_64_64(efdsub);
8221GEN_SPEFPUOP_ARITH2_64_64(efdmul);
8222GEN_SPEFPUOP_ARITH2_64_64(efddiv);
636aa200 8223static inline void gen_efdabs(DisasContext *ctx)
1c97856d
AJ
8224{
8225 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8226 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8227 return;
8228 }
8229#if defined(TARGET_PPC64)
6d5c34fa 8230 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
1c97856d 8231#else
6d5c34fa
MP
8232 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8233 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
1c97856d
AJ
8234#endif
8235}
636aa200 8236static inline void gen_efdnabs(DisasContext *ctx)
1c97856d
AJ
8237{
8238 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8239 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8240 return;
8241 }
8242#if defined(TARGET_PPC64)
6d5c34fa 8243 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
1c97856d 8244#else
6d5c34fa
MP
8245 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8246 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8247#endif
8248}
636aa200 8249static inline void gen_efdneg(DisasContext *ctx)
1c97856d
AJ
8250{
8251 if (unlikely(!ctx->spe_enabled)) {
27a69bb0 8252 gen_exception(ctx, POWERPC_EXCP_SPEU);
1c97856d
AJ
8253 return;
8254 }
8255#if defined(TARGET_PPC64)
6d5c34fa 8256 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
1c97856d 8257#else
6d5c34fa
MP
8258 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
8259 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
1c97856d
AJ
8260#endif
8261}
8262
0487d6a8 8263/* Conversion */
1c97856d
AJ
8264GEN_SPEFPUOP_CONV_64_32(efdcfui);
8265GEN_SPEFPUOP_CONV_64_32(efdcfsi);
8266GEN_SPEFPUOP_CONV_64_32(efdcfuf);
8267GEN_SPEFPUOP_CONV_64_32(efdcfsf);
8268GEN_SPEFPUOP_CONV_32_64(efdctui);
8269GEN_SPEFPUOP_CONV_32_64(efdctsi);
8270GEN_SPEFPUOP_CONV_32_64(efdctuf);
8271GEN_SPEFPUOP_CONV_32_64(efdctsf);
8272GEN_SPEFPUOP_CONV_32_64(efdctuiz);
8273GEN_SPEFPUOP_CONV_32_64(efdctsiz);
8274GEN_SPEFPUOP_CONV_64_32(efdcfs);
8275GEN_SPEFPUOP_CONV_64_64(efdcfuid);
8276GEN_SPEFPUOP_CONV_64_64(efdcfsid);
8277GEN_SPEFPUOP_CONV_64_64(efdctuidz);
8278GEN_SPEFPUOP_CONV_64_64(efdctsidz);
0487d6a8 8279
0487d6a8 8280/* Comparison */
1c97856d
AJ
8281GEN_SPEFPUOP_COMP_64(efdcmpgt);
8282GEN_SPEFPUOP_COMP_64(efdcmplt);
8283GEN_SPEFPUOP_COMP_64(efdcmpeq);
8284GEN_SPEFPUOP_COMP_64(efdtstgt);
8285GEN_SPEFPUOP_COMP_64(efdtstlt);
8286GEN_SPEFPUOP_COMP_64(efdtsteq);
0487d6a8
JM
8287
8288/* Opcodes definitions */
40569b7e
AJ
8289GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
8290GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8291GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
8292GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
8293GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
8294GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8295GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
8296GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
8297GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8298GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8299GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8300GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8301GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8302GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
8303GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
8304GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
0487d6a8 8305
c227f099 8306static opcode_t opcodes[] = {
5c55ff99
BS
8307GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
8308GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
8309GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
8310GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
8311GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
8312GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
8313GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8314GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8315GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8316GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8317GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
8318GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
8319GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
8320GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER),
8321GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8322#if defined(TARGET_PPC64)
8323GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
8324#endif
8325GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
8326GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
8327GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8328GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8329GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8330GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
8331GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER),
8332GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER),
8333GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8334GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8335GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8336GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8337GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
eaabeef2 8338GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
5c55ff99 8339#if defined(TARGET_PPC64)
eaabeef2 8340GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
5c55ff99
BS
8341GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
8342#endif
8343GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8344GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8345GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8346GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER),
8347GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER),
8348GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER),
8349GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER),
8350#if defined(TARGET_PPC64)
8351GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B),
8352GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B),
8353GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B),
8354GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B),
8355GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B),
8356#endif
8357GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
8358GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8359GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
8360GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
8361GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
8362GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
8363GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
8364GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
8365GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
8366GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
8367GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT),
8368GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT),
8369#if defined(TARGET_PPC64)
8370GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
8371GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
8372GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
8373#endif
8374GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8375GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
8376GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
8377GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
8378GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
8379GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
8380GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
8381GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
f844c817 8382GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
5c55ff99
BS
8383GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
8384#if defined(TARGET_PPC64)
f844c817 8385GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
5c55ff99
BS
8386GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
8387#endif
8388GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
8389GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
8390GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8391GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8392GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),
8393GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW),
8394GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER),
8395GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
8396#if defined(TARGET_PPC64)
8397GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
8398GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
8399#endif
8400GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
8401GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
8402GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
8403#if defined(TARGET_PPC64)
8404GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B),
8405GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B),
8406#endif
8407GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC),
8408GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC),
8409GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC),
8410GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC),
8411GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB),
8412GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
8413#if defined(TARGET_PPC64)
8414GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
8415#endif
8416GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC),
8417GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC),
8418GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
8419GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
8420GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE),
8421GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE),
8422GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE),
8423GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ),
8424GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT),
8425GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
8426GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
8427GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
8428GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
8429GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
8430GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT),
8431GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT),
8432GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT),
8433GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT),
8434#if defined(TARGET_PPC64)
8435GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B),
8436GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
8437 PPC_SEGMENT_64B),
8438GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B),
8439GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
8440 PPC_SEGMENT_64B),
efdef95f
DG
8441GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
8442GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
8443GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
5c55ff99
BS
8444#endif
8445GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
8446GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE),
8447GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE),
8448GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
8449#if defined(TARGET_PPC64)
8450GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
8451GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
8452#endif
8453GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
8454GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN),
8455GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR),
8456GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR),
8457GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR),
8458GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR),
8459GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR),
8460GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR),
8461GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR),
8462GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR),
8463GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR),
8464GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8465GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR),
8466GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR),
8467GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR),
8468GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR),
8469GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR),
8470GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR),
8471GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR),
8472GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR),
8473GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR),
8474GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR),
8475GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR),
8476GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR),
8477GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR),
8478GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR),
8479GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR),
8480GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR),
8481GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR),
8482GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR),
8483GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR),
8484GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR),
8485GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR),
8486GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR),
8487GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR),
8488GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR),
8489GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC),
8490GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC),
8491GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC),
8492GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB),
8493GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB),
8494GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB),
8495GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB),
8496GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER),
8497GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER),
8498GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER),
8499GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER),
8500GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER),
8501GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER),
8502GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8503GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8504GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2),
8505GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2),
8506GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8507GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2),
8508GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2),
8509GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2),
8510GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI),
8511GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA),
8512GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR),
8513GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR),
8514GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX),
8515GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX),
8516GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX),
8517GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX),
8518GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON),
8519GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON),
8520GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
8521GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
8522GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
8523GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
01662f3e 8524GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
5c55ff99
BS
8525GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
8526GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
8527GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
8528GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB),
8529GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
8530GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
8531GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
8532GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
01662f3e
AG
8533GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
8534 PPC_NONE, PPC2_BOOKE206),
8535GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
8536 PPC_NONE, PPC2_BOOKE206),
8537GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
8538 PPC_NONE, PPC2_BOOKE206),
8539GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
8540 PPC_NONE, PPC2_BOOKE206),
5c55ff99 8541GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
fbe73008 8542GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
5c55ff99 8543GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
01662f3e
AG
8544GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
8545 PPC_BOOKE, PPC2_BOOKE206),
8546GEN_HANDLER_E(msync, 0x1F, 0x16, 0x12, 0x03FFF801,
8547 PPC_BOOKE, PPC2_BOOKE206),
8548GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
8549 PPC_BOOKE, PPC2_BOOKE206),
5c55ff99
BS
8550GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
8551GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
8552GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
8553GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC),
8554GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC),
8555GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
8556GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE),
8557GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE),
8558GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE),
8559GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE),
8560
8561#undef GEN_INT_ARITH_ADD
8562#undef GEN_INT_ARITH_ADD_CONST
8563#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
8564GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
8565#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
8566 add_ca, compute_ca, compute_ov) \
8567GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
8568GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
8569GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
8570GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
8571GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
8572GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
8573GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
8574GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
8575GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
8576GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
8577GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
8578
8579#undef GEN_INT_ARITH_DIVW
8580#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
8581GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
8582GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
8583GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
8584GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
8585GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
8586
8587#if defined(TARGET_PPC64)
8588#undef GEN_INT_ARITH_DIVD
8589#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
8590GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8591GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0),
8592GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
8593GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
8594GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
8595
8596#undef GEN_INT_ARITH_MUL_HELPER
8597#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
8598GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
8599GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00),
8600GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
8601GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
8602#endif
8603
8604#undef GEN_INT_ARITH_SUBF
8605#undef GEN_INT_ARITH_SUBF_CONST
8606#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
8607GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
8608#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
8609 add_ca, compute_ca, compute_ov) \
8610GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
8611GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
8612GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
8613GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
8614GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
8615GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
8616GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
8617GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
8618GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
8619GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
8620GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
8621
8622#undef GEN_LOGICAL1
8623#undef GEN_LOGICAL2
8624#define GEN_LOGICAL2(name, tcg_op, opc, type) \
8625GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type)
8626#define GEN_LOGICAL1(name, tcg_op, opc, type) \
8627GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)
8628GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER),
8629GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER),
8630GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER),
8631GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER),
8632GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER),
8633GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER),
8634GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER),
8635GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER),
8636#if defined(TARGET_PPC64)
8637GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B),
8638#endif
8639
8640#if defined(TARGET_PPC64)
8641#undef GEN_PPC64_R2
8642#undef GEN_PPC64_R4
8643#define GEN_PPC64_R2(name, opc1, opc2) \
8644GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8645GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
8646 PPC_64B)
8647#define GEN_PPC64_R4(name, opc1, opc2) \
8648GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\
8649GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
8650 PPC_64B), \
8651GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
8652 PPC_64B), \
8653GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
8654 PPC_64B)
8655GEN_PPC64_R4(rldicl, 0x1E, 0x00),
8656GEN_PPC64_R4(rldicr, 0x1E, 0x02),
8657GEN_PPC64_R4(rldic, 0x1E, 0x04),
8658GEN_PPC64_R2(rldcl, 0x1E, 0x08),
8659GEN_PPC64_R2(rldcr, 0x1E, 0x09),
8660GEN_PPC64_R4(rldimi, 0x1E, 0x06),
8661#endif
8662
8663#undef _GEN_FLOAT_ACB
8664#undef GEN_FLOAT_ACB
8665#undef _GEN_FLOAT_AB
8666#undef GEN_FLOAT_AB
8667#undef _GEN_FLOAT_AC
8668#undef GEN_FLOAT_AC
8669#undef GEN_FLOAT_B
8670#undef GEN_FLOAT_BS
8671#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
8672GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)
8673#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
8674_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type), \
8675_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type)
8676#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
8677GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8678#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
8679_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
8680_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8681#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
8682GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)
8683#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
8684_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type), \
8685_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type)
8686#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
8687GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)
8688#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
8689GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)
8690
8691GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT),
8692GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT),
8693GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
8694GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
8695GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
8696GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
8697_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
8698GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
8699GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
8700GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
8701GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
8702GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
8703GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
8704GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
8705GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
8706#if defined(TARGET_PPC64)
8707GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B),
8708GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B),
8709GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B),
8710#endif
8711GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
8712GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
8713GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
8714GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
8715GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT),
8716GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT),
8717GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),
8718
8719#undef GEN_LD
8720#undef GEN_LDU
8721#undef GEN_LDUX
8722#undef GEN_LDX
8723#undef GEN_LDS
8724#define GEN_LD(name, ldop, opc, type) \
8725GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8726#define GEN_LDU(name, ldop, opc, type) \
8727GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8728#define GEN_LDUX(name, ldop, opc2, opc3, type) \
8729GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8730#define GEN_LDX(name, ldop, opc2, opc3, type) \
8731GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8732#define GEN_LDS(name, ldop, op, type) \
8733GEN_LD(name, ldop, op | 0x20, type) \
8734GEN_LDU(name, ldop, op | 0x21, type) \
8735GEN_LDUX(name, ldop, 0x17, op | 0x01, type) \
8736GEN_LDX(name, ldop, 0x17, op | 0x00, type)
8737
8738GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER)
8739GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER)
8740GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER)
8741GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER)
8742#if defined(TARGET_PPC64)
8743GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
8744GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
8745GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
8746GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
8747#endif
8748GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
8749GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
8750
8751#undef GEN_ST
8752#undef GEN_STU
8753#undef GEN_STUX
8754#undef GEN_STX
8755#undef GEN_STS
8756#define GEN_ST(name, stop, opc, type) \
8757GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8758#define GEN_STU(name, stop, opc, type) \
8759GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
8760#define GEN_STUX(name, stop, opc2, opc3, type) \
8761GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
8762#define GEN_STX(name, stop, opc2, opc3, type) \
8763GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8764#define GEN_STS(name, stop, op, type) \
8765GEN_ST(name, stop, op | 0x20, type) \
8766GEN_STU(name, stop, op | 0x21, type) \
8767GEN_STUX(name, stop, 0x17, op | 0x01, type) \
8768GEN_STX(name, stop, 0x17, op | 0x00, type)
8769
8770GEN_STS(stb, st8, 0x06, PPC_INTEGER)
8771GEN_STS(sth, st16, 0x0C, PPC_INTEGER)
8772GEN_STS(stw, st32, 0x04, PPC_INTEGER)
8773#if defined(TARGET_PPC64)
8774GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
8775GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
8776#endif
8777GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
8778GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
8779
8780#undef GEN_LDF
8781#undef GEN_LDUF
8782#undef GEN_LDUXF
8783#undef GEN_LDXF
8784#undef GEN_LDFS
8785#define GEN_LDF(name, ldop, opc, type) \
8786GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8787#define GEN_LDUF(name, ldop, opc, type) \
8788GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8789#define GEN_LDUXF(name, ldop, opc, type) \
8790GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8791#define GEN_LDXF(name, ldop, opc2, opc3, type) \
8792GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8793#define GEN_LDFS(name, ldop, op, type) \
8794GEN_LDF(name, ldop, op | 0x20, type) \
8795GEN_LDUF(name, ldop, op | 0x21, type) \
8796GEN_LDUXF(name, ldop, op | 0x01, type) \
8797GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
8798
8799GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
8800GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
8801
8802#undef GEN_STF
8803#undef GEN_STUF
8804#undef GEN_STUXF
8805#undef GEN_STXF
8806#undef GEN_STFS
8807#define GEN_STF(name, stop, opc, type) \
8808GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
8809#define GEN_STUF(name, stop, opc, type) \
8810GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
8811#define GEN_STUXF(name, stop, opc, type) \
8812GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
8813#define GEN_STXF(name, stop, opc2, opc3, type) \
8814GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
8815#define GEN_STFS(name, stop, op, type) \
8816GEN_STF(name, stop, op | 0x20, type) \
8817GEN_STUF(name, stop, op | 0x21, type) \
8818GEN_STUXF(name, stop, op | 0x01, type) \
8819GEN_STXF(name, stop, 0x17, op | 0x00, type)
8820
8821GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
8822GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
8823GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
8824
8825#undef GEN_CRLOGIC
8826#define GEN_CRLOGIC(name, tcg_op, opc) \
8827GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)
8828GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08),
8829GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04),
8830GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09),
8831GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07),
8832GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01),
8833GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E),
8834GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D),
8835GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06),
8836
8837#undef GEN_MAC_HANDLER
8838#define GEN_MAC_HANDLER(name, opc2, opc3) \
8839GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)
8840GEN_MAC_HANDLER(macchw, 0x0C, 0x05),
8841GEN_MAC_HANDLER(macchwo, 0x0C, 0x15),
8842GEN_MAC_HANDLER(macchws, 0x0C, 0x07),
8843GEN_MAC_HANDLER(macchwso, 0x0C, 0x17),
8844GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06),
8845GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16),
8846GEN_MAC_HANDLER(macchwu, 0x0C, 0x04),
8847GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14),
8848GEN_MAC_HANDLER(machhw, 0x0C, 0x01),
8849GEN_MAC_HANDLER(machhwo, 0x0C, 0x11),
8850GEN_MAC_HANDLER(machhws, 0x0C, 0x03),
8851GEN_MAC_HANDLER(machhwso, 0x0C, 0x13),
8852GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02),
8853GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12),
8854GEN_MAC_HANDLER(machhwu, 0x0C, 0x00),
8855GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10),
8856GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D),
8857GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D),
8858GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F),
8859GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F),
8860GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C),
8861GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C),
8862GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E),
8863GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E),
8864GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05),
8865GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15),
8866GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07),
8867GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17),
8868GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01),
8869GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11),
8870GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03),
8871GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13),
8872GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D),
8873GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D),
8874GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F),
8875GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F),
8876GEN_MAC_HANDLER(mulchw, 0x08, 0x05),
8877GEN_MAC_HANDLER(mulchwu, 0x08, 0x04),
8878GEN_MAC_HANDLER(mulhhw, 0x08, 0x01),
8879GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00),
8880GEN_MAC_HANDLER(mullhw, 0x08, 0x0D),
8881GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C),
8882
8883#undef GEN_VR_LDX
8884#undef GEN_VR_STX
8885#undef GEN_VR_LVE
8886#undef GEN_VR_STVE
8887#define GEN_VR_LDX(name, opc2, opc3) \
8888GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8889#define GEN_VR_STX(name, opc2, opc3) \
8890GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8891#define GEN_VR_LVE(name, opc2, opc3) \
8892 GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8893#define GEN_VR_STVE(name, opc2, opc3) \
8894 GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)
8895GEN_VR_LDX(lvx, 0x07, 0x03),
8896GEN_VR_LDX(lvxl, 0x07, 0x0B),
8897GEN_VR_LVE(bx, 0x07, 0x00),
8898GEN_VR_LVE(hx, 0x07, 0x01),
8899GEN_VR_LVE(wx, 0x07, 0x02),
8900GEN_VR_STX(svx, 0x07, 0x07),
8901GEN_VR_STX(svxl, 0x07, 0x0F),
8902GEN_VR_STVE(bx, 0x07, 0x04),
8903GEN_VR_STVE(hx, 0x07, 0x05),
8904GEN_VR_STVE(wx, 0x07, 0x06),
8905
8906#undef GEN_VX_LOGICAL
8907#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
8908GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8909GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16),
8910GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17),
8911GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18),
8912GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19),
8913GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20),
8914
8915#undef GEN_VXFORM
8916#define GEN_VXFORM(name, opc2, opc3) \
8917GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
8918GEN_VXFORM(vaddubm, 0, 0),
8919GEN_VXFORM(vadduhm, 0, 1),
8920GEN_VXFORM(vadduwm, 0, 2),
8921GEN_VXFORM(vsububm, 0, 16),
8922GEN_VXFORM(vsubuhm, 0, 17),
8923GEN_VXFORM(vsubuwm, 0, 18),
8924GEN_VXFORM(vmaxub, 1, 0),
8925GEN_VXFORM(vmaxuh, 1, 1),
8926GEN_VXFORM(vmaxuw, 1, 2),
8927GEN_VXFORM(vmaxsb, 1, 4),
8928GEN_VXFORM(vmaxsh, 1, 5),
8929GEN_VXFORM(vmaxsw, 1, 6),
8930GEN_VXFORM(vminub, 1, 8),
8931GEN_VXFORM(vminuh, 1, 9),
8932GEN_VXFORM(vminuw, 1, 10),
8933GEN_VXFORM(vminsb, 1, 12),
8934GEN_VXFORM(vminsh, 1, 13),
8935GEN_VXFORM(vminsw, 1, 14),
8936GEN_VXFORM(vavgub, 1, 16),
8937GEN_VXFORM(vavguh, 1, 17),
8938GEN_VXFORM(vavguw, 1, 18),
8939GEN_VXFORM(vavgsb, 1, 20),
8940GEN_VXFORM(vavgsh, 1, 21),
8941GEN_VXFORM(vavgsw, 1, 22),
8942GEN_VXFORM(vmrghb, 6, 0),
8943GEN_VXFORM(vmrghh, 6, 1),
8944GEN_VXFORM(vmrghw, 6, 2),
8945GEN_VXFORM(vmrglb, 6, 4),
8946GEN_VXFORM(vmrglh, 6, 5),
8947GEN_VXFORM(vmrglw, 6, 6),
8948GEN_VXFORM(vmuloub, 4, 0),
8949GEN_VXFORM(vmulouh, 4, 1),
8950GEN_VXFORM(vmulosb, 4, 4),
8951GEN_VXFORM(vmulosh, 4, 5),
8952GEN_VXFORM(vmuleub, 4, 8),
8953GEN_VXFORM(vmuleuh, 4, 9),
8954GEN_VXFORM(vmulesb, 4, 12),
8955GEN_VXFORM(vmulesh, 4, 13),
8956GEN_VXFORM(vslb, 2, 4),
8957GEN_VXFORM(vslh, 2, 5),
8958GEN_VXFORM(vslw, 2, 6),
8959GEN_VXFORM(vsrb, 2, 8),
8960GEN_VXFORM(vsrh, 2, 9),
8961GEN_VXFORM(vsrw, 2, 10),
8962GEN_VXFORM(vsrab, 2, 12),
8963GEN_VXFORM(vsrah, 2, 13),
8964GEN_VXFORM(vsraw, 2, 14),
8965GEN_VXFORM(vslo, 6, 16),
8966GEN_VXFORM(vsro, 6, 17),
8967GEN_VXFORM(vaddcuw, 0, 6),
8968GEN_VXFORM(vsubcuw, 0, 22),
8969GEN_VXFORM(vaddubs, 0, 8),
8970GEN_VXFORM(vadduhs, 0, 9),
8971GEN_VXFORM(vadduws, 0, 10),
8972GEN_VXFORM(vaddsbs, 0, 12),
8973GEN_VXFORM(vaddshs, 0, 13),
8974GEN_VXFORM(vaddsws, 0, 14),
8975GEN_VXFORM(vsububs, 0, 24),
8976GEN_VXFORM(vsubuhs, 0, 25),
8977GEN_VXFORM(vsubuws, 0, 26),
8978GEN_VXFORM(vsubsbs, 0, 28),
8979GEN_VXFORM(vsubshs, 0, 29),
8980GEN_VXFORM(vsubsws, 0, 30),
8981GEN_VXFORM(vrlb, 2, 0),
8982GEN_VXFORM(vrlh, 2, 1),
8983GEN_VXFORM(vrlw, 2, 2),
8984GEN_VXFORM(vsl, 2, 7),
8985GEN_VXFORM(vsr, 2, 11),
8986GEN_VXFORM(vpkuhum, 7, 0),
8987GEN_VXFORM(vpkuwum, 7, 1),
8988GEN_VXFORM(vpkuhus, 7, 2),
8989GEN_VXFORM(vpkuwus, 7, 3),
8990GEN_VXFORM(vpkshus, 7, 4),
8991GEN_VXFORM(vpkswus, 7, 5),
8992GEN_VXFORM(vpkshss, 7, 6),
8993GEN_VXFORM(vpkswss, 7, 7),
8994GEN_VXFORM(vpkpx, 7, 12),
8995GEN_VXFORM(vsum4ubs, 4, 24),
8996GEN_VXFORM(vsum4sbs, 4, 28),
8997GEN_VXFORM(vsum4shs, 4, 25),
8998GEN_VXFORM(vsum2sws, 4, 26),
8999GEN_VXFORM(vsumsws, 4, 30),
9000GEN_VXFORM(vaddfp, 5, 0),
9001GEN_VXFORM(vsubfp, 5, 1),
9002GEN_VXFORM(vmaxfp, 5, 16),
9003GEN_VXFORM(vminfp, 5, 17),
9004
9005#undef GEN_VXRFORM1
9006#undef GEN_VXRFORM
9007#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
9008 GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC),
9009#define GEN_VXRFORM(name, opc2, opc3) \
9010 GEN_VXRFORM1(name, name, #name, opc2, opc3) \
9011 GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
9012GEN_VXRFORM(vcmpequb, 3, 0)
9013GEN_VXRFORM(vcmpequh, 3, 1)
9014GEN_VXRFORM(vcmpequw, 3, 2)
9015GEN_VXRFORM(vcmpgtsb, 3, 12)
9016GEN_VXRFORM(vcmpgtsh, 3, 13)
9017GEN_VXRFORM(vcmpgtsw, 3, 14)
9018GEN_VXRFORM(vcmpgtub, 3, 8)
9019GEN_VXRFORM(vcmpgtuh, 3, 9)
9020GEN_VXRFORM(vcmpgtuw, 3, 10)
9021GEN_VXRFORM(vcmpeqfp, 3, 3)
9022GEN_VXRFORM(vcmpgefp, 3, 7)
9023GEN_VXRFORM(vcmpgtfp, 3, 11)
9024GEN_VXRFORM(vcmpbfp, 3, 15)
9025
9026#undef GEN_VXFORM_SIMM
9027#define GEN_VXFORM_SIMM(name, opc2, opc3) \
9028 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9029GEN_VXFORM_SIMM(vspltisb, 6, 12),
9030GEN_VXFORM_SIMM(vspltish, 6, 13),
9031GEN_VXFORM_SIMM(vspltisw, 6, 14),
9032
9033#undef GEN_VXFORM_NOA
9034#define GEN_VXFORM_NOA(name, opc2, opc3) \
9035 GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
9036GEN_VXFORM_NOA(vupkhsb, 7, 8),
9037GEN_VXFORM_NOA(vupkhsh, 7, 9),
9038GEN_VXFORM_NOA(vupklsb, 7, 10),
9039GEN_VXFORM_NOA(vupklsh, 7, 11),
9040GEN_VXFORM_NOA(vupkhpx, 7, 13),
9041GEN_VXFORM_NOA(vupklpx, 7, 15),
9042GEN_VXFORM_NOA(vrefp, 5, 4),
9043GEN_VXFORM_NOA(vrsqrtefp, 5, 5),
0bffbc6c 9044GEN_VXFORM_NOA(vexptefp, 5, 6),
5c55ff99
BS
9045GEN_VXFORM_NOA(vlogefp, 5, 7),
9046GEN_VXFORM_NOA(vrfim, 5, 8),
9047GEN_VXFORM_NOA(vrfin, 5, 9),
9048GEN_VXFORM_NOA(vrfip, 5, 10),
9049GEN_VXFORM_NOA(vrfiz, 5, 11),
9050
9051#undef GEN_VXFORM_UIMM
9052#define GEN_VXFORM_UIMM(name, opc2, opc3) \
9053 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC)
9054GEN_VXFORM_UIMM(vspltb, 6, 8),
9055GEN_VXFORM_UIMM(vsplth, 6, 9),
9056GEN_VXFORM_UIMM(vspltw, 6, 10),
9057GEN_VXFORM_UIMM(vcfux, 5, 12),
9058GEN_VXFORM_UIMM(vcfsx, 5, 13),
9059GEN_VXFORM_UIMM(vctuxs, 5, 14),
9060GEN_VXFORM_UIMM(vctsxs, 5, 15),
9061
9062#undef GEN_VAFORM_PAIRED
9063#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
9064 GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
9065GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
9066GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
9067GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
9068GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
9069GEN_VAFORM_PAIRED(vsel, vperm, 21),
9070GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
9071
9072#undef GEN_SPE
9073#define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
9074GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)
9075GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE),
9076GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE),
9077GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE),
9078GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE),
9079GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE),
9080GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE),
9081GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE),
9082GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE),
a0e13900 9083GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, PPC_SPE),
5c55ff99
BS
9084GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE),
9085GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE),
9086GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE),
9087GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE),
a0e13900
FC
9088GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE),
9089GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE),
9090GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE),
5c55ff99
BS
9091GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE),
9092GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE),
9093GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE),
9094GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE),
9095GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE),
9096GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE),
9097GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE),
9098GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE),
9099GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE),
9100GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE),
9101GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE),
9102GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE),
9103GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE),
9104
9105GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE),
9106GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE),
9107GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE),
9108GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE),
9109GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE),
9110GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE),
9111GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE),
9112GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE),
9113GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE),
9114GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE),
9115GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE),
9116GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE),
9117GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE),
9118GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE),
9119
9120GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE),
9121GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE),
9122GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE),
9123GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE),
9124GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE),
9125GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE),
9126GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE),
9127GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE),
9128GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE),
9129GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE),
9130GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE),
9131GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE),
9132GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE),
9133GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE),
9134
9135GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
9136GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
9137GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
9138GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE),
9139GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE),
9140GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
9141GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
9142GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
9143GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
9144GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
9145GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
9146GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
9147GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
9148GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE),
9149GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
9150GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE),
9151
9152#undef GEN_SPEOP_LDST
9153#define GEN_SPEOP_LDST(name, opc2, sh) \
9154GEN_HANDLER(name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE)
9155GEN_SPEOP_LDST(evldd, 0x00, 3),
9156GEN_SPEOP_LDST(evldw, 0x01, 3),
9157GEN_SPEOP_LDST(evldh, 0x02, 3),
9158GEN_SPEOP_LDST(evlhhesplat, 0x04, 1),
9159GEN_SPEOP_LDST(evlhhousplat, 0x06, 1),
9160GEN_SPEOP_LDST(evlhhossplat, 0x07, 1),
9161GEN_SPEOP_LDST(evlwhe, 0x08, 2),
9162GEN_SPEOP_LDST(evlwhou, 0x0A, 2),
9163GEN_SPEOP_LDST(evlwhos, 0x0B, 2),
9164GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2),
9165GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2),
9166
9167GEN_SPEOP_LDST(evstdd, 0x10, 3),
9168GEN_SPEOP_LDST(evstdw, 0x11, 3),
9169GEN_SPEOP_LDST(evstdh, 0x12, 3),
9170GEN_SPEOP_LDST(evstwhe, 0x18, 2),
9171GEN_SPEOP_LDST(evstwho, 0x1A, 2),
9172GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
9173GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
9174};
9175
3fc6c082 9176#include "translate_init.c"
0411a972 9177#include "helper_regs.h"
79aceca5 9178
9a64fbe4 9179/*****************************************************************************/
3fc6c082 9180/* Misc PowerPC helpers */
9a78eead 9181void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
36081602 9182 int flags)
79aceca5 9183{
3fc6c082
FB
9184#define RGPL 4
9185#define RFPL 4
3fc6c082 9186
79aceca5
FB
9187 int i;
9188
90e189ec 9189 cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR "
9a78eead
SW
9190 TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
9191 env->nip, env->lr, env->ctr, env->xer);
90e189ec
BS
9192 cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF "
9193 TARGET_FMT_lx " idx %d\n", env->msr, env->spr[SPR_HID0],
9194 env->hflags, env->mmu_idx);
d9bce9d9 9195#if !defined(NO_TIMER_DUMP)
9a78eead 9196 cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
76a66253 9197#if !defined(CONFIG_USER_ONLY)
9a78eead 9198 " DECR %08" PRIu32
76a66253
JM
9199#endif
9200 "\n",
077fc206 9201 cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
76a66253
JM
9202#if !defined(CONFIG_USER_ONLY)
9203 , cpu_ppc_load_decr(env)
9204#endif
9205 );
077fc206 9206#endif
76a66253 9207 for (i = 0; i < 32; i++) {
3fc6c082
FB
9208 if ((i & (RGPL - 1)) == 0)
9209 cpu_fprintf(f, "GPR%02d", i);
b11ebf64 9210 cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
3fc6c082 9211 if ((i & (RGPL - 1)) == (RGPL - 1))
7fe48483 9212 cpu_fprintf(f, "\n");
76a66253 9213 }
3fc6c082 9214 cpu_fprintf(f, "CR ");
76a66253 9215 for (i = 0; i < 8; i++)
7fe48483
FB
9216 cpu_fprintf(f, "%01x", env->crf[i]);
9217 cpu_fprintf(f, " [");
76a66253
JM
9218 for (i = 0; i < 8; i++) {
9219 char a = '-';
9220 if (env->crf[i] & 0x08)
9221 a = 'L';
9222 else if (env->crf[i] & 0x04)
9223 a = 'G';
9224 else if (env->crf[i] & 0x02)
9225 a = 'E';
7fe48483 9226 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
76a66253 9227 }
90e189ec
BS
9228 cpu_fprintf(f, " ] RES " TARGET_FMT_lx "\n",
9229 env->reserve_addr);
3fc6c082
FB
9230 for (i = 0; i < 32; i++) {
9231 if ((i & (RFPL - 1)) == 0)
9232 cpu_fprintf(f, "FPR%02d", i);
26a76461 9233 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
3fc6c082 9234 if ((i & (RFPL - 1)) == (RFPL - 1))
7fe48483 9235 cpu_fprintf(f, "\n");
79aceca5 9236 }
7889270a 9237 cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
f2e63a42 9238#if !defined(CONFIG_USER_ONLY)
90dc8812
SW
9239 cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx
9240 " PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
9241 env->spr[SPR_SRR0], env->spr[SPR_SRR1],
9242 env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);
9243
9244 cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
9245 " SPRG2 " TARGET_FMT_lx " SPRG3 " TARGET_FMT_lx "\n",
9246 env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
9247 env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);
9248
9249 cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
9250 " SPRG6 " TARGET_FMT_lx " SPRG7 " TARGET_FMT_lx "\n",
9251 env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
9252 env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
9253
9254 if (env->excp_model == POWERPC_EXCP_BOOKE) {
9255 cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
9256 " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
9257 env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
9258 env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
9259
9260 cpu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
9261 " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
9262 env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
9263 env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
9264
9265 cpu_fprintf(f, " PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
9266 " IVPR " TARGET_FMT_lx " EPCR " TARGET_FMT_lx "\n",
9267 env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
9268 env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);
9269
9270 cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
9271 " EPR " TARGET_FMT_lx "\n",
9272 env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
9273 env->spr[SPR_BOOKE_EPR]);
9274
9275 /* FSL-specific */
9276 cpu_fprintf(f, " MCAR " TARGET_FMT_lx " PID1 " TARGET_FMT_lx
9277 " PID2 " TARGET_FMT_lx " SVR " TARGET_FMT_lx "\n",
9278 env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
9279 env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);
9280
9281 /*
9282 * IVORs are left out as they are large and do not change often --
9283 * they can be read with "p $ivor0", "p $ivor1", etc.
9284 */
9285 }
9286
697ab892
DG
9287#if defined(TARGET_PPC64)
9288 if (env->flags & POWERPC_FLAG_CFAR) {
9289 cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
9290 }
9291#endif
9292
90dc8812
SW
9293 switch (env->mmu_model) {
9294 case POWERPC_MMU_32B:
9295 case POWERPC_MMU_601:
9296 case POWERPC_MMU_SOFT_6xx:
9297 case POWERPC_MMU_SOFT_74xx:
9298#if defined(TARGET_PPC64)
9299 case POWERPC_MMU_620:
9300 case POWERPC_MMU_64B:
9301#endif
9302 cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
9303 break;
01662f3e 9304 case POWERPC_MMU_BOOKE206:
90dc8812
SW
9305 cpu_fprintf(f, " MAS0 " TARGET_FMT_lx " MAS1 " TARGET_FMT_lx
9306 " MAS2 " TARGET_FMT_lx " MAS3 " TARGET_FMT_lx "\n",
9307 env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
9308 env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);
9309
9310 cpu_fprintf(f, " MAS4 " TARGET_FMT_lx " MAS6 " TARGET_FMT_lx
9311 " MAS7 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n",
9312 env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
9313 env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);
9314
9315 cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
9316 " TLB1CFG " TARGET_FMT_lx "\n",
9317 env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
9318 env->spr[SPR_BOOKE_TLB1CFG]);
9319 break;
9320 default:
9321 break;
9322 }
f2e63a42 9323#endif
79aceca5 9324
3fc6c082
FB
9325#undef RGPL
9326#undef RFPL
79aceca5
FB
9327}
9328
9a78eead 9329void cpu_dump_statistics (CPUState *env, FILE*f, fprintf_function cpu_fprintf,
76a66253
JM
9330 int flags)
9331{
9332#if defined(DO_PPC_STATISTICS)
c227f099 9333 opc_handler_t **t1, **t2, **t3, *handler;
76a66253
JM
9334 int op1, op2, op3;
9335
9336 t1 = env->opcodes;
9337 for (op1 = 0; op1 < 64; op1++) {
9338 handler = t1[op1];
9339 if (is_indirect_opcode(handler)) {
9340 t2 = ind_table(handler);
9341 for (op2 = 0; op2 < 32; op2++) {
9342 handler = t2[op2];
9343 if (is_indirect_opcode(handler)) {
9344 t3 = ind_table(handler);
9345 for (op3 = 0; op3 < 32; op3++) {
9346 handler = t3[op3];
9347 if (handler->count == 0)
9348 continue;
9349 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
0bfcd599 9350 "%016" PRIx64 " %" PRId64 "\n",
76a66253
JM
9351 op1, op2, op3, op1, (op3 << 5) | op2,
9352 handler->oname,
9353 handler->count, handler->count);
9354 }
9355 } else {
9356 if (handler->count == 0)
9357 continue;
9358 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
0bfcd599 9359 "%016" PRIx64 " %" PRId64 "\n",
76a66253
JM
9360 op1, op2, op1, op2, handler->oname,
9361 handler->count, handler->count);
9362 }
9363 }
9364 } else {
9365 if (handler->count == 0)
9366 continue;
0bfcd599
BS
9367 cpu_fprintf(f, "%02x (%02x ) %16s: %016" PRIx64
9368 " %" PRId64 "\n",
76a66253
JM
9369 op1, op1, handler->oname,
9370 handler->count, handler->count);
9371 }
9372 }
9373#endif
9374}
9375
9a64fbe4 9376/*****************************************************************************/
636aa200
BS
9377static inline void gen_intermediate_code_internal(CPUState *env,
9378 TranslationBlock *tb,
9379 int search_pc)
79aceca5 9380{
9fddaa0c 9381 DisasContext ctx, *ctxp = &ctx;
c227f099 9382 opc_handler_t **table, *handler;
0fa85d43 9383 target_ulong pc_start;
79aceca5 9384 uint16_t *gen_opc_end;
a1d1bb31 9385 CPUBreakpoint *bp;
79aceca5 9386 int j, lj = -1;
2e70f6ef
PB
9387 int num_insns;
9388 int max_insns;
79aceca5
FB
9389
9390 pc_start = tb->pc;
79aceca5 9391 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
046d6672 9392 ctx.nip = pc_start;
79aceca5 9393 ctx.tb = tb;
e1833e1f 9394 ctx.exception = POWERPC_EXCP_NONE;
3fc6c082 9395 ctx.spr_cb = env->spr_cb;
76db3ba4
AJ
9396 ctx.mem_idx = env->mmu_idx;
9397 ctx.access_type = -1;
9398 ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
d9bce9d9
JM
9399#if defined(TARGET_PPC64)
9400 ctx.sf_mode = msr_sf;
697ab892 9401 ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
9a64fbe4 9402#endif
3cc62370 9403 ctx.fpu_enabled = msr_fp;
a9d9eb8f 9404 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
d26bfc9a
JM
9405 ctx.spe_enabled = msr_spe;
9406 else
9407 ctx.spe_enabled = 0;
a9d9eb8f
JM
9408 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
9409 ctx.altivec_enabled = msr_vr;
9410 else
9411 ctx.altivec_enabled = 0;
d26bfc9a 9412 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8cbcb4fa 9413 ctx.singlestep_enabled = CPU_SINGLE_STEP;
d26bfc9a 9414 else
8cbcb4fa 9415 ctx.singlestep_enabled = 0;
d26bfc9a 9416 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8cbcb4fa
AJ
9417 ctx.singlestep_enabled |= CPU_BRANCH_STEP;
9418 if (unlikely(env->singlestep_enabled))
9419 ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
3fc6c082 9420#if defined (DO_SINGLE_STEP) && 0
9a64fbe4
FB
9421 /* Single step trace mode */
9422 msr_se = 1;
9423#endif
2e70f6ef
PB
9424 num_insns = 0;
9425 max_insns = tb->cflags & CF_COUNT_MASK;
9426 if (max_insns == 0)
9427 max_insns = CF_COUNT_MASK;
9428
9429 gen_icount_start();
9a64fbe4 9430 /* Set env in case of segfault during code fetch */
e1833e1f 9431 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
72cf2d4f
BS
9432 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9433 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 9434 if (bp->pc == ctx.nip) {
e06fcd75 9435 gen_debug_exception(ctxp);
ea4e754f
FB
9436 break;
9437 }
9438 }
9439 }
76a66253 9440 if (unlikely(search_pc)) {
79aceca5
FB
9441 j = gen_opc_ptr - gen_opc_buf;
9442 if (lj < j) {
9443 lj++;
9444 while (lj < j)
9445 gen_opc_instr_start[lj++] = 0;
79aceca5 9446 }
af4b6c54
AJ
9447 gen_opc_pc[lj] = ctx.nip;
9448 gen_opc_instr_start[lj] = 1;
9449 gen_opc_icount[lj] = num_insns;
79aceca5 9450 }
d12d51d5 9451 LOG_DISAS("----------------\n");
90e189ec 9452 LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
d12d51d5 9453 ctx.nip, ctx.mem_idx, (int)msr_ir);
2e70f6ef
PB
9454 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9455 gen_io_start();
76db3ba4 9456 if (unlikely(ctx.le_mode)) {
056401ea
JM
9457 ctx.opcode = bswap32(ldl_code(ctx.nip));
9458 } else {
9459 ctx.opcode = ldl_code(ctx.nip);
111bfab3 9460 }
d12d51d5 9461 LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
9a64fbe4 9462 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
056401ea 9463 opc3(ctx.opcode), little_endian ? "little" : "big");
731c54f8
AJ
9464 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
9465 tcg_gen_debug_insn_start(ctx.nip);
046d6672 9466 ctx.nip += 4;
3fc6c082 9467 table = env->opcodes;
2e70f6ef 9468 num_insns++;
79aceca5
FB
9469 handler = table[opc1(ctx.opcode)];
9470 if (is_indirect_opcode(handler)) {
9471 table = ind_table(handler);
9472 handler = table[opc2(ctx.opcode)];
9473 if (is_indirect_opcode(handler)) {
9474 table = ind_table(handler);
9475 handler = table[opc3(ctx.opcode)];
9476 }
9477 }
9478 /* Is opcode *REALLY* valid ? */
76a66253 9479 if (unlikely(handler->handler == &gen_invalid)) {
93fcfe39
AL
9480 if (qemu_log_enabled()) {
9481 qemu_log("invalid/unsupported opcode: "
90e189ec
BS
9482 "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
9483 opc1(ctx.opcode), opc2(ctx.opcode),
9484 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
4b3686fa 9485 }
76a66253
JM
9486 } else {
9487 if (unlikely((ctx.opcode & handler->inval) != 0)) {
93fcfe39
AL
9488 if (qemu_log_enabled()) {
9489 qemu_log("invalid bits: %08x for opcode: "
90e189ec
BS
9490 "%02x - %02x - %02x (%08x) " TARGET_FMT_lx "\n",
9491 ctx.opcode & handler->inval, opc1(ctx.opcode),
9492 opc2(ctx.opcode), opc3(ctx.opcode),
9493 ctx.opcode, ctx.nip - 4);
76a66253 9494 }
e06fcd75 9495 gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
4b3686fa 9496 break;
79aceca5 9497 }
79aceca5 9498 }
4b3686fa 9499 (*(handler->handler))(&ctx);
76a66253
JM
9500#if defined(DO_PPC_STATISTICS)
9501 handler->count++;
9502#endif
9a64fbe4 9503 /* Check trace mode exceptions */
8cbcb4fa
AJ
9504 if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
9505 (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
9506 ctx.exception != POWERPC_SYSCALL &&
9507 ctx.exception != POWERPC_EXCP_TRAP &&
9508 ctx.exception != POWERPC_EXCP_BRANCH)) {
e06fcd75 9509 gen_exception(ctxp, POWERPC_EXCP_TRACE);
d26bfc9a 9510 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
2e70f6ef 9511 (env->singlestep_enabled) ||
1b530a6d 9512 singlestep ||
2e70f6ef 9513 num_insns >= max_insns)) {
d26bfc9a
JM
9514 /* if we reach a page boundary or are single stepping, stop
9515 * generation
9516 */
8dd4983c 9517 break;
76a66253 9518 }
3fc6c082 9519 }
2e70f6ef
PB
9520 if (tb->cflags & CF_LAST_IO)
9521 gen_io_end();
e1833e1f 9522 if (ctx.exception == POWERPC_EXCP_NONE) {
c1942362 9523 gen_goto_tb(&ctx, 0, ctx.nip);
e1833e1f 9524 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
8cbcb4fa 9525 if (unlikely(env->singlestep_enabled)) {
e06fcd75 9526 gen_debug_exception(ctxp);
8cbcb4fa 9527 }
76a66253 9528 /* Generate the return instruction */
57fec1fe 9529 tcg_gen_exit_tb(0);
9a64fbe4 9530 }
2e70f6ef 9531 gen_icount_end(tb, num_insns);
79aceca5 9532 *gen_opc_ptr = INDEX_op_end;
76a66253 9533 if (unlikely(search_pc)) {
9a64fbe4
FB
9534 j = gen_opc_ptr - gen_opc_buf;
9535 lj++;
9536 while (lj <= j)
9537 gen_opc_instr_start[lj++] = 0;
9a64fbe4 9538 } else {
046d6672 9539 tb->size = ctx.nip - pc_start;
2e70f6ef 9540 tb->icount = num_insns;
9a64fbe4 9541 }
d9bce9d9 9542#if defined(DEBUG_DISAS)
8fec2b8c 9543 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
76a66253 9544 int flags;
237c0af0 9545 flags = env->bfd_mach;
76db3ba4 9546 flags |= ctx.le_mode << 16;
93fcfe39
AL
9547 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9548 log_target_disas(pc_start, ctx.nip - pc_start, flags);
9549 qemu_log("\n");
9fddaa0c 9550 }
79aceca5 9551#endif
79aceca5
FB
9552}
9553
2cfc5f17 9554void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
79aceca5 9555{
2cfc5f17 9556 gen_intermediate_code_internal(env, tb, 0);
79aceca5
FB
9557}
9558
2cfc5f17 9559void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
79aceca5 9560{
2cfc5f17 9561 gen_intermediate_code_internal(env, tb, 1);
79aceca5 9562}
d2856f1a 9563
e87b7cb0 9564void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
d2856f1a 9565{
d2856f1a 9566 env->nip = gen_opc_pc[pc_pos];
d2856f1a 9567}