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