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