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