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