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