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