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