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