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