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