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