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