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