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