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