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