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