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