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