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