]> git.ipfire.org Git - thirdparty/qemu.git/blame - target-ppc/translate.c
Implement PowerPC Altivec load & stores, used by Apple firmware for memcpy.
[thirdparty/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 */
e1833e1f 3300GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
79aceca5 3301{
e1833e1f
JM
3302 uint32_t lev;
3303
3304 lev = (ctx->opcode >> 5) & 0x7F;
9a64fbe4 3305#if defined(CONFIG_USER_ONLY)
e1833e1f 3306 GEN_EXCP(ctx, POWERPC_EXCP_SYSCALL_USER, lev);
9a64fbe4 3307#else
e1833e1f 3308 GEN_EXCP(ctx, POWERPC_EXCP_SYSCALL, lev);
9a64fbe4 3309#endif
79aceca5
FB
3310}
3311
3312/*** Trap ***/
3313/* tw */
76a66253 3314GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
79aceca5 3315{
9a64fbe4
FB
3316 gen_op_load_gpr_T0(rA(ctx->opcode));
3317 gen_op_load_gpr_T1(rB(ctx->opcode));
a0ae05aa 3318 /* Update the nip since this might generate a trap exception */
d9bce9d9 3319 gen_update_nip(ctx, ctx->nip);
9a64fbe4 3320 gen_op_tw(TO(ctx->opcode));
79aceca5
FB
3321}
3322
3323/* twi */
3324GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3325{
9a64fbe4 3326 gen_op_load_gpr_T0(rA(ctx->opcode));
d9bce9d9
JM
3327 gen_set_T1(SIMM(ctx->opcode));
3328 /* Update the nip since this might generate a trap exception */
3329 gen_update_nip(ctx, ctx->nip);
76a66253 3330 gen_op_tw(TO(ctx->opcode));
79aceca5
FB
3331}
3332
d9bce9d9
JM
3333#if defined(TARGET_PPC64)
3334/* td */
3335GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
3336{
3337 gen_op_load_gpr_T0(rA(ctx->opcode));
3338 gen_op_load_gpr_T1(rB(ctx->opcode));
3339 /* Update the nip since this might generate a trap exception */
3340 gen_update_nip(ctx, ctx->nip);
3341 gen_op_td(TO(ctx->opcode));
3342}
3343
3344/* tdi */
3345GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
3346{
3347 gen_op_load_gpr_T0(rA(ctx->opcode));
3348 gen_set_T1(SIMM(ctx->opcode));
3349 /* Update the nip since this might generate a trap exception */
3350 gen_update_nip(ctx, ctx->nip);
3351 gen_op_td(TO(ctx->opcode));
3352}
3353#endif
3354
79aceca5 3355/*** Processor control ***/
79aceca5
FB
3356/* mcrxr */
3357GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
3358{
3359 gen_op_load_xer_cr();
3360 gen_op_store_T0_crf(crfD(ctx->opcode));
e864cabd
JM
3361 gen_op_clear_xer_ov();
3362 gen_op_clear_xer_ca();
79aceca5
FB
3363}
3364
3365/* mfcr */
76a66253 3366GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
79aceca5 3367{
76a66253 3368 uint32_t crm, crn;
3b46e624 3369
76a66253
JM
3370 if (likely(ctx->opcode & 0x00100000)) {
3371 crm = CRM(ctx->opcode);
3372 if (likely((crm ^ (crm - 1)) == 0)) {
3373 crn = ffs(crm);
3374 gen_op_load_cro(7 - crn);
3375 }
d9bce9d9
JM
3376 } else {
3377 gen_op_load_cr();
3378 }
79aceca5 3379 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
3380}
3381
3382/* mfmsr */
3383GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
3384{
9a64fbe4 3385#if defined(CONFIG_USER_ONLY)
e1833e1f 3386 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 3387#else
76a66253 3388 if (unlikely(!ctx->supervisor)) {
e1833e1f 3389 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 3390 return;
9a64fbe4 3391 }
79aceca5
FB
3392 gen_op_load_msr();
3393 gen_op_store_T0_gpr(rD(ctx->opcode));
9a64fbe4 3394#endif
79aceca5
FB
3395}
3396
3fc6c082
FB
3397#if 0
3398#define SPR_NOACCESS ((void *)(-1))
3399#else
3400static void spr_noaccess (void *opaque, int sprn)
3401{
3402 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3403 printf("ERROR: try to access SPR %d !\n", sprn);
3404}
3405#define SPR_NOACCESS (&spr_noaccess)
3406#endif
3407
79aceca5 3408/* mfspr */
b068d6a7 3409static always_inline void gen_op_mfspr (DisasContext *ctx)
79aceca5 3410{
3fc6c082 3411 void (*read_cb)(void *opaque, int sprn);
79aceca5
FB
3412 uint32_t sprn = SPR(ctx->opcode);
3413
3fc6c082 3414#if !defined(CONFIG_USER_ONLY)
be147d08
JM
3415#if defined(TARGET_PPC64H)
3416 if (ctx->supervisor == 2)
3417 read_cb = ctx->spr_cb[sprn].hea_read;
3418 else
3419#endif
3fc6c082
FB
3420 if (ctx->supervisor)
3421 read_cb = ctx->spr_cb[sprn].oea_read;
3422 else
9a64fbe4 3423#endif
3fc6c082 3424 read_cb = ctx->spr_cb[sprn].uea_read;
76a66253
JM
3425 if (likely(read_cb != NULL)) {
3426 if (likely(read_cb != SPR_NOACCESS)) {
3fc6c082
FB
3427 (*read_cb)(ctx, sprn);
3428 gen_op_store_T0_gpr(rD(ctx->opcode));
3429 } else {
3430 /* Privilege exception */
4a057712 3431 if (loglevel != 0) {
7f75ffd3 3432 fprintf(logfile, "Trying to read privileged spr %d %03x\n",
f24e5695
FB
3433 sprn, sprn);
3434 }
7f75ffd3 3435 printf("Trying to read privileged spr %d %03x\n", sprn, sprn);
e1833e1f 3436 GEN_EXCP_PRIVREG(ctx);
79aceca5 3437 }
3fc6c082
FB
3438 } else {
3439 /* Not defined */
4a057712 3440 if (loglevel != 0) {
f24e5695
FB
3441 fprintf(logfile, "Trying to read invalid spr %d %03x\n",
3442 sprn, sprn);
3443 }
3fc6c082 3444 printf("Trying to read invalid spr %d %03x\n", sprn, sprn);
e1833e1f
JM
3445 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3446 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
79aceca5 3447 }
79aceca5
FB
3448}
3449
3fc6c082 3450GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
79aceca5 3451{
3fc6c082 3452 gen_op_mfspr(ctx);
76a66253 3453}
3fc6c082
FB
3454
3455/* mftb */
a750fc0b 3456GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3fc6c082
FB
3457{
3458 gen_op_mfspr(ctx);
79aceca5
FB
3459}
3460
3461/* mtcrf */
8dd4983c 3462GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
79aceca5 3463{
76a66253 3464 uint32_t crm, crn;
3b46e624 3465
79aceca5 3466 gen_op_load_gpr_T0(rS(ctx->opcode));
76a66253
JM
3467 crm = CRM(ctx->opcode);
3468 if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
3469 crn = ffs(crm);
3470 gen_op_srli_T0(crn * 4);
3471 gen_op_andi_T0(0xF);
3472 gen_op_store_cro(7 - crn);
3473 } else {
3474 gen_op_store_cr(crm);
3475 }
79aceca5
FB
3476}
3477
3478/* mtmsr */
426613db 3479#if defined(TARGET_PPC64)
be147d08 3480GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
426613db
JM
3481{
3482#if defined(CONFIG_USER_ONLY)
e1833e1f 3483 GEN_EXCP_PRIVREG(ctx);
426613db
JM
3484#else
3485 if (unlikely(!ctx->supervisor)) {
e1833e1f 3486 GEN_EXCP_PRIVREG(ctx);
426613db
JM
3487 return;
3488 }
426613db 3489 gen_op_load_gpr_T0(rS(ctx->opcode));
be147d08
JM
3490 if (ctx->opcode & 0x00010000) {
3491 /* Special form that does not need any synchronisation */
3492 gen_op_update_riee();
3493 } else {
056b05f8
JM
3494 /* XXX: we need to update nip before the store
3495 * if we enter power saving mode, we will exit the loop
3496 * directly from ppc_store_msr
3497 */
be147d08
JM
3498 gen_update_nip(ctx, ctx->nip);
3499 gen_op_store_msr();
3500 /* Must stop the translation as machine state (may have) changed */
3501 /* Note that mtmsr is not always defined as context-synchronizing */
056b05f8 3502 ctx->exception = POWERPC_EXCP_STOP;
be147d08 3503 }
426613db
JM
3504#endif
3505}
3506#endif
3507
79aceca5
FB
3508GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
3509{
9a64fbe4 3510#if defined(CONFIG_USER_ONLY)
e1833e1f 3511 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 3512#else
76a66253 3513 if (unlikely(!ctx->supervisor)) {
e1833e1f 3514 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 3515 return;
9a64fbe4 3516 }
79aceca5 3517 gen_op_load_gpr_T0(rS(ctx->opcode));
be147d08
JM
3518 if (ctx->opcode & 0x00010000) {
3519 /* Special form that does not need any synchronisation */
3520 gen_op_update_riee();
3521 } else {
056b05f8
JM
3522 /* XXX: we need to update nip before the store
3523 * if we enter power saving mode, we will exit the loop
3524 * directly from ppc_store_msr
3525 */
be147d08 3526 gen_update_nip(ctx, ctx->nip);
d9bce9d9 3527#if defined(TARGET_PPC64)
be147d08
JM
3528 if (!ctx->sf_mode)
3529 gen_op_store_msr_32();
3530 else
d9bce9d9 3531#endif
be147d08
JM
3532 gen_op_store_msr();
3533 /* Must stop the translation as machine state (may have) changed */
3534 /* Note that mtmsrd is not always defined as context-synchronizing */
056b05f8 3535 ctx->exception = POWERPC_EXCP_STOP;
be147d08 3536 }
9a64fbe4 3537#endif
79aceca5
FB
3538}
3539
3540/* mtspr */
3541GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
3542{
3fc6c082 3543 void (*write_cb)(void *opaque, int sprn);
79aceca5
FB
3544 uint32_t sprn = SPR(ctx->opcode);
3545
3fc6c082 3546#if !defined(CONFIG_USER_ONLY)
be147d08
JM
3547#if defined(TARGET_PPC64H)
3548 if (ctx->supervisor == 2)
3549 write_cb = ctx->spr_cb[sprn].hea_write;
3550 else
3551#endif
3fc6c082
FB
3552 if (ctx->supervisor)
3553 write_cb = ctx->spr_cb[sprn].oea_write;
3554 else
9a64fbe4 3555#endif
3fc6c082 3556 write_cb = ctx->spr_cb[sprn].uea_write;
76a66253
JM
3557 if (likely(write_cb != NULL)) {
3558 if (likely(write_cb != SPR_NOACCESS)) {
3fc6c082
FB
3559 gen_op_load_gpr_T0(rS(ctx->opcode));
3560 (*write_cb)(ctx, sprn);
3561 } else {
3562 /* Privilege exception */
4a057712 3563 if (loglevel != 0) {
7f75ffd3 3564 fprintf(logfile, "Trying to write privileged spr %d %03x\n",
f24e5695
FB
3565 sprn, sprn);
3566 }
7f75ffd3 3567 printf("Trying to write privileged spr %d %03x\n", sprn, sprn);
e1833e1f 3568 GEN_EXCP_PRIVREG(ctx);
76a66253 3569 }
3fc6c082
FB
3570 } else {
3571 /* Not defined */
4a057712 3572 if (loglevel != 0) {
f24e5695
FB
3573 fprintf(logfile, "Trying to write invalid spr %d %03x\n",
3574 sprn, sprn);
3575 }
3fc6c082 3576 printf("Trying to write invalid spr %d %03x\n", sprn, sprn);
e1833e1f
JM
3577 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3578 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
79aceca5 3579 }
79aceca5
FB
3580}
3581
3582/*** Cache management ***/
3583/* For now, all those will be implemented as nop:
3584 * this is valid, regarding the PowerPC specs...
9a64fbe4 3585 * We just have to flush tb while invalidating instruction cache lines...
79aceca5
FB
3586 */
3587/* dcbf */
0db1b20e 3588GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
79aceca5 3589{
76a66253 3590 gen_addr_reg_index(ctx);
a541f297 3591 op_ldst(lbz);
79aceca5
FB
3592}
3593
3594/* dcbi (Supervisor only) */
9a64fbe4 3595GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
79aceca5 3596{
a541f297 3597#if defined(CONFIG_USER_ONLY)
e1833e1f 3598 GEN_EXCP_PRIVOPC(ctx);
a541f297 3599#else
76a66253 3600 if (unlikely(!ctx->supervisor)) {
e1833e1f 3601 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 3602 return;
9a64fbe4 3603 }
76a66253
JM
3604 gen_addr_reg_index(ctx);
3605 /* XXX: specification says this should be treated as a store by the MMU */
3606 //op_ldst(lbz);
a541f297
FB
3607 op_ldst(stb);
3608#endif
79aceca5
FB
3609}
3610
3611/* dcdst */
9a64fbe4 3612GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
79aceca5 3613{
76a66253
JM
3614 /* XXX: specification say this is treated as a load by the MMU */
3615 gen_addr_reg_index(ctx);
a541f297 3616 op_ldst(lbz);
79aceca5
FB
3617}
3618
3619/* dcbt */
0db1b20e 3620GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
79aceca5 3621{
0db1b20e 3622 /* interpreted as no-op */
76a66253
JM
3623 /* XXX: specification say this is treated as a load by the MMU
3624 * but does not generate any exception
3625 */
79aceca5
FB
3626}
3627
3628/* dcbtst */
0db1b20e 3629GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
79aceca5 3630{
0db1b20e 3631 /* interpreted as no-op */
76a66253
JM
3632 /* XXX: specification say this is treated as a load by the MMU
3633 * but does not generate any exception
3634 */
79aceca5
FB
3635}
3636
3637/* dcbz */
d63001d1 3638#define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
d9bce9d9 3639#if defined(CONFIG_USER_ONLY)
2857068e 3640/* User-mode only */
d63001d1
JM
3641static GenOpFunc *gen_op_dcbz[4][4] = {
3642 {
3643 &gen_op_dcbz_l32_raw,
3644 &gen_op_dcbz_l32_raw,
2857068e 3645#if defined(TARGET_PPC64)
d63001d1
JM
3646 &gen_op_dcbz_l32_64_raw,
3647 &gen_op_dcbz_l32_64_raw,
2857068e 3648#endif
d63001d1
JM
3649 },
3650 {
3651 &gen_op_dcbz_l64_raw,
3652 &gen_op_dcbz_l64_raw,
3653#if defined(TARGET_PPC64)
3654 &gen_op_dcbz_l64_64_raw,
3655 &gen_op_dcbz_l64_64_raw,
3656#endif
3657 },
3658 {
3659 &gen_op_dcbz_l128_raw,
3660 &gen_op_dcbz_l128_raw,
3661#if defined(TARGET_PPC64)
3662 &gen_op_dcbz_l128_64_raw,
3663 &gen_op_dcbz_l128_64_raw,
3664#endif
3665 },
3666 {
3667 &gen_op_dcbz_raw,
3668 &gen_op_dcbz_raw,
3669#if defined(TARGET_PPC64)
3670 &gen_op_dcbz_64_raw,
3671 &gen_op_dcbz_64_raw,
3672#endif
3673 },
d9bce9d9
JM
3674};
3675#else
2857068e
JM
3676#if defined(TARGET_PPC64)
3677/* Full system - 64 bits mode */
d63001d1
JM
3678static GenOpFunc *gen_op_dcbz[4][12] = {
3679 {
3680 &gen_op_dcbz_l32_user,
3681 &gen_op_dcbz_l32_user,
3682 &gen_op_dcbz_l32_64_user,
3683 &gen_op_dcbz_l32_64_user,
3684 &gen_op_dcbz_l32_kernel,
3685 &gen_op_dcbz_l32_kernel,
3686 &gen_op_dcbz_l32_64_kernel,
3687 &gen_op_dcbz_l32_64_kernel,
3688#if defined(TARGET_PPC64H)
3689 &gen_op_dcbz_l32_hypv,
3690 &gen_op_dcbz_l32_hypv,
3691 &gen_op_dcbz_l32_64_hypv,
3692 &gen_op_dcbz_l32_64_hypv,
3693#endif
3694 },
3695 {
3696 &gen_op_dcbz_l64_user,
3697 &gen_op_dcbz_l64_user,
3698 &gen_op_dcbz_l64_64_user,
3699 &gen_op_dcbz_l64_64_user,
3700 &gen_op_dcbz_l64_kernel,
3701 &gen_op_dcbz_l64_kernel,
3702 &gen_op_dcbz_l64_64_kernel,
3703 &gen_op_dcbz_l64_64_kernel,
2857068e 3704#if defined(TARGET_PPC64H)
d63001d1
JM
3705 &gen_op_dcbz_l64_hypv,
3706 &gen_op_dcbz_l64_hypv,
3707 &gen_op_dcbz_l64_64_hypv,
3708 &gen_op_dcbz_l64_64_hypv,
3709#endif
3710 },
3711 {
3712 &gen_op_dcbz_l128_user,
3713 &gen_op_dcbz_l128_user,
3714 &gen_op_dcbz_l128_64_user,
3715 &gen_op_dcbz_l128_64_user,
3716 &gen_op_dcbz_l128_kernel,
3717 &gen_op_dcbz_l128_kernel,
3718 &gen_op_dcbz_l128_64_kernel,
3719 &gen_op_dcbz_l128_64_kernel,
3720#if defined(TARGET_PPC64H)
3721 &gen_op_dcbz_l128_hypv,
3722 &gen_op_dcbz_l128_hypv,
3723 &gen_op_dcbz_l128_64_hypv,
3724 &gen_op_dcbz_l128_64_hypv,
3725#endif
3726 },
3727 {
3728 &gen_op_dcbz_user,
3729 &gen_op_dcbz_user,
3730 &gen_op_dcbz_64_user,
3731 &gen_op_dcbz_64_user,
3732 &gen_op_dcbz_kernel,
3733 &gen_op_dcbz_kernel,
3734 &gen_op_dcbz_64_kernel,
3735 &gen_op_dcbz_64_kernel,
3736#if defined(TARGET_PPC64H)
3737 &gen_op_dcbz_hypv,
3738 &gen_op_dcbz_hypv,
3739 &gen_op_dcbz_64_hypv,
3740 &gen_op_dcbz_64_hypv,
d9bce9d9 3741#endif
d63001d1 3742 },
76a66253 3743};
9a64fbe4 3744#else
2857068e 3745/* Full system - 32 bits mode */
d63001d1
JM
3746static GenOpFunc *gen_op_dcbz[4][4] = {
3747 {
3748 &gen_op_dcbz_l32_user,
3749 &gen_op_dcbz_l32_user,
3750 &gen_op_dcbz_l32_kernel,
3751 &gen_op_dcbz_l32_kernel,
3752 },
3753 {
3754 &gen_op_dcbz_l64_user,
3755 &gen_op_dcbz_l64_user,
3756 &gen_op_dcbz_l64_kernel,
3757 &gen_op_dcbz_l64_kernel,
3758 },
3759 {
3760 &gen_op_dcbz_l128_user,
3761 &gen_op_dcbz_l128_user,
3762 &gen_op_dcbz_l128_kernel,
3763 &gen_op_dcbz_l128_kernel,
3764 },
3765 {
3766 &gen_op_dcbz_user,
3767 &gen_op_dcbz_user,
3768 &gen_op_dcbz_kernel,
3769 &gen_op_dcbz_kernel,
3770 },
9a64fbe4
FB
3771};
3772#endif
d9bce9d9 3773#endif
9a64fbe4 3774
b068d6a7
JM
3775static always_inline void handler_dcbz (DisasContext *ctx,
3776 int dcache_line_size)
d63001d1
JM
3777{
3778 int n;
3779
3780 switch (dcache_line_size) {
3781 case 32:
3782 n = 0;
3783 break;
3784 case 64:
3785 n = 1;
3786 break;
3787 case 128:
3788 n = 2;
3789 break;
3790 default:
3791 n = 3;
3792 break;
3793 }
3794 op_dcbz(n);
3795}
3796
3797GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
79aceca5 3798{
76a66253 3799 gen_addr_reg_index(ctx);
d63001d1
JM
3800 handler_dcbz(ctx, ctx->dcache_line_size);
3801 gen_op_check_reservation();
3802}
3803
3804GEN_HANDLER(dcbz_970, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
3805{
3806 gen_addr_reg_index(ctx);
3807 if (ctx->opcode & 0x00200000)
3808 handler_dcbz(ctx, ctx->dcache_line_size);
3809 else
3810 handler_dcbz(ctx, -1);
4b3686fa 3811 gen_op_check_reservation();
79aceca5
FB
3812}
3813
3814/* icbi */
36f69651 3815#define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
36f69651 3816#if defined(CONFIG_USER_ONLY)
2857068e 3817/* User-mode only */
36f69651
JM
3818static GenOpFunc *gen_op_icbi[] = {
3819 &gen_op_icbi_raw,
3820 &gen_op_icbi_raw,
2857068e 3821#if defined(TARGET_PPC64)
36f69651
JM
3822 &gen_op_icbi_64_raw,
3823 &gen_op_icbi_64_raw,
2857068e 3824#endif
36f69651
JM
3825};
3826#else
2857068e
JM
3827/* Full system - 64 bits mode */
3828#if defined(TARGET_PPC64)
36f69651
JM
3829static GenOpFunc *gen_op_icbi[] = {
3830 &gen_op_icbi_user,
3831 &gen_op_icbi_user,
36f69651
JM
3832 &gen_op_icbi_64_user,
3833 &gen_op_icbi_64_user,
2857068e
JM
3834 &gen_op_icbi_kernel,
3835 &gen_op_icbi_kernel,
36f69651
JM
3836 &gen_op_icbi_64_kernel,
3837 &gen_op_icbi_64_kernel,
2857068e
JM
3838#if defined(TARGET_PPC64H)
3839 &gen_op_icbi_hypv,
3840 &gen_op_icbi_hypv,
3841 &gen_op_icbi_64_hypv,
3842 &gen_op_icbi_64_hypv,
36f69651 3843#endif
36f69651
JM
3844};
3845#else
2857068e 3846/* Full system - 32 bits mode */
36f69651
JM
3847static GenOpFunc *gen_op_icbi[] = {
3848 &gen_op_icbi_user,
3849 &gen_op_icbi_user,
3850 &gen_op_icbi_kernel,
3851 &gen_op_icbi_kernel,
3852};
3853#endif
3854#endif
e1833e1f 3855
9a64fbe4 3856GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
79aceca5 3857{
30032c94
JM
3858 /* NIP cannot be restored if the memory exception comes from an helper */
3859 gen_update_nip(ctx, ctx->nip - 4);
76a66253 3860 gen_addr_reg_index(ctx);
36f69651 3861 op_icbi();
79aceca5
FB
3862}
3863
3864/* Optional: */
3865/* dcba */
a750fc0b 3866GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
79aceca5 3867{
0db1b20e
JM
3868 /* interpreted as no-op */
3869 /* XXX: specification say this is treated as a store by the MMU
3870 * but does not generate any exception
3871 */
79aceca5
FB
3872}
3873
3874/*** Segment register manipulation ***/
3875/* Supervisor only: */
3876/* mfsr */
3877GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
3878{
9a64fbe4 3879#if defined(CONFIG_USER_ONLY)
e1833e1f 3880 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 3881#else
76a66253 3882 if (unlikely(!ctx->supervisor)) {
e1833e1f 3883 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 3884 return;
9a64fbe4 3885 }
76a66253
JM
3886 gen_op_set_T1(SR(ctx->opcode));
3887 gen_op_load_sr();
9a64fbe4
FB
3888 gen_op_store_T0_gpr(rD(ctx->opcode));
3889#endif
79aceca5
FB
3890}
3891
3892/* mfsrin */
9a64fbe4 3893GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
79aceca5 3894{
9a64fbe4 3895#if defined(CONFIG_USER_ONLY)
e1833e1f 3896 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 3897#else
76a66253 3898 if (unlikely(!ctx->supervisor)) {
e1833e1f 3899 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 3900 return;
9a64fbe4
FB
3901 }
3902 gen_op_load_gpr_T1(rB(ctx->opcode));
76a66253
JM
3903 gen_op_srli_T1(28);
3904 gen_op_load_sr();
9a64fbe4
FB
3905 gen_op_store_T0_gpr(rD(ctx->opcode));
3906#endif
79aceca5
FB
3907}
3908
3909/* mtsr */
e63c59cb 3910GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
79aceca5 3911{
9a64fbe4 3912#if defined(CONFIG_USER_ONLY)
e1833e1f 3913 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 3914#else
76a66253 3915 if (unlikely(!ctx->supervisor)) {
e1833e1f 3916 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 3917 return;
9a64fbe4
FB
3918 }
3919 gen_op_load_gpr_T0(rS(ctx->opcode));
76a66253
JM
3920 gen_op_set_T1(SR(ctx->opcode));
3921 gen_op_store_sr();
9a64fbe4 3922#endif
79aceca5
FB
3923}
3924
3925/* mtsrin */
9a64fbe4 3926GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
79aceca5 3927{
9a64fbe4 3928#if defined(CONFIG_USER_ONLY)
e1833e1f 3929 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 3930#else
76a66253 3931 if (unlikely(!ctx->supervisor)) {
e1833e1f 3932 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 3933 return;
9a64fbe4
FB
3934 }
3935 gen_op_load_gpr_T0(rS(ctx->opcode));
3936 gen_op_load_gpr_T1(rB(ctx->opcode));
76a66253
JM
3937 gen_op_srli_T1(28);
3938 gen_op_store_sr();
9a64fbe4 3939#endif
79aceca5
FB
3940}
3941
12de9a39
JM
3942#if defined(TARGET_PPC64)
3943/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
3944/* mfsr */
3945GEN_HANDLER(mfsr_64b, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
3946{
3947#if defined(CONFIG_USER_ONLY)
3948 GEN_EXCP_PRIVREG(ctx);
3949#else
3950 if (unlikely(!ctx->supervisor)) {
3951 GEN_EXCP_PRIVREG(ctx);
3952 return;
3953 }
3954 gen_op_set_T1(SR(ctx->opcode));
3955 gen_op_load_slb();
3956 gen_op_store_T0_gpr(rD(ctx->opcode));
3957#endif
3958}
3959
3960/* mfsrin */
3961GEN_HANDLER(mfsrin_64b, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT_64B)
3962{
3963#if defined(CONFIG_USER_ONLY)
3964 GEN_EXCP_PRIVREG(ctx);
3965#else
3966 if (unlikely(!ctx->supervisor)) {
3967 GEN_EXCP_PRIVREG(ctx);
3968 return;
3969 }
3970 gen_op_load_gpr_T1(rB(ctx->opcode));
3971 gen_op_srli_T1(28);
3972 gen_op_load_slb();
3973 gen_op_store_T0_gpr(rD(ctx->opcode));
3974#endif
3975}
3976
3977/* mtsr */
3978GEN_HANDLER(mtsr_64b, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
3979{
3980#if defined(CONFIG_USER_ONLY)
3981 GEN_EXCP_PRIVREG(ctx);
3982#else
3983 if (unlikely(!ctx->supervisor)) {
3984 GEN_EXCP_PRIVREG(ctx);
3985 return;
3986 }
3987 gen_op_load_gpr_T0(rS(ctx->opcode));
3988 gen_op_set_T1(SR(ctx->opcode));
3989 gen_op_store_slb();
3990#endif
3991}
3992
3993/* mtsrin */
3994GEN_HANDLER(mtsrin_64b, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT_64B)
3995{
3996#if defined(CONFIG_USER_ONLY)
3997 GEN_EXCP_PRIVREG(ctx);
3998#else
3999 if (unlikely(!ctx->supervisor)) {
4000 GEN_EXCP_PRIVREG(ctx);
4001 return;
4002 }
4003 gen_op_load_gpr_T0(rS(ctx->opcode));
4004 gen_op_load_gpr_T1(rB(ctx->opcode));
4005 gen_op_srli_T1(28);
4006 gen_op_store_slb();
4007#endif
4008}
4009#endif /* defined(TARGET_PPC64) */
4010
79aceca5
FB
4011/*** Lookaside buffer management ***/
4012/* Optional & supervisor only: */
4013/* tlbia */
3fc6c082 4014GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
79aceca5 4015{
9a64fbe4 4016#if defined(CONFIG_USER_ONLY)
e1833e1f 4017 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4 4018#else
76a66253 4019 if (unlikely(!ctx->supervisor)) {
4a057712 4020 if (loglevel != 0)
9fddaa0c 4021 fprintf(logfile, "%s: ! supervisor\n", __func__);
e1833e1f 4022 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4023 return;
9a64fbe4
FB
4024 }
4025 gen_op_tlbia();
4026#endif
79aceca5
FB
4027}
4028
4029/* tlbie */
76a66253 4030GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
79aceca5 4031{
9a64fbe4 4032#if defined(CONFIG_USER_ONLY)
e1833e1f 4033 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4 4034#else
76a66253 4035 if (unlikely(!ctx->supervisor)) {
e1833e1f 4036 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4037 return;
9a64fbe4
FB
4038 }
4039 gen_op_load_gpr_T0(rB(ctx->opcode));
d9bce9d9
JM
4040#if defined(TARGET_PPC64)
4041 if (ctx->sf_mode)
4042 gen_op_tlbie_64();
4043 else
4044#endif
4045 gen_op_tlbie();
9a64fbe4 4046#endif
79aceca5
FB
4047}
4048
4049/* tlbsync */
76a66253 4050GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
79aceca5 4051{
9a64fbe4 4052#if defined(CONFIG_USER_ONLY)
e1833e1f 4053 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4 4054#else
76a66253 4055 if (unlikely(!ctx->supervisor)) {
e1833e1f 4056 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4057 return;
9a64fbe4
FB
4058 }
4059 /* This has no effect: it should ensure that all previous
4060 * tlbie have completed
4061 */
e1833e1f 4062 GEN_STOP(ctx);
9a64fbe4 4063#endif
79aceca5
FB
4064}
4065
426613db
JM
4066#if defined(TARGET_PPC64)
4067/* slbia */
4068GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
4069{
4070#if defined(CONFIG_USER_ONLY)
e1833e1f 4071 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4072#else
4073 if (unlikely(!ctx->supervisor)) {
4a057712 4074 if (loglevel != 0)
426613db 4075 fprintf(logfile, "%s: ! supervisor\n", __func__);
e1833e1f 4076 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4077 return;
4078 }
4079 gen_op_slbia();
426613db
JM
4080#endif
4081}
4082
4083/* slbie */
4084GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
4085{
4086#if defined(CONFIG_USER_ONLY)
e1833e1f 4087 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4088#else
4089 if (unlikely(!ctx->supervisor)) {
e1833e1f 4090 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4091 return;
4092 }
4093 gen_op_load_gpr_T0(rB(ctx->opcode));
4094 gen_op_slbie();
426613db
JM
4095#endif
4096}
4097#endif
4098
79aceca5
FB
4099/*** External control ***/
4100/* Optional: */
9a64fbe4
FB
4101#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
4102#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
111bfab3 4103#if defined(CONFIG_USER_ONLY)
2857068e 4104/* User-mode only */
111bfab3
FB
4105static GenOpFunc *gen_op_eciwx[] = {
4106 &gen_op_eciwx_raw,
4107 &gen_op_eciwx_le_raw,
2857068e 4108#if defined(TARGET_PPC64)
d9bce9d9
JM
4109 &gen_op_eciwx_64_raw,
4110 &gen_op_eciwx_le_64_raw,
2857068e 4111#endif
111bfab3
FB
4112};
4113static GenOpFunc *gen_op_ecowx[] = {
4114 &gen_op_ecowx_raw,
4115 &gen_op_ecowx_le_raw,
2857068e 4116#if defined(TARGET_PPC64)
d9bce9d9
JM
4117 &gen_op_ecowx_64_raw,
4118 &gen_op_ecowx_le_64_raw,
2857068e 4119#endif
111bfab3
FB
4120};
4121#else
2857068e
JM
4122#if defined(TARGET_PPC64)
4123/* Full system - 64 bits mode */
9a64fbe4
FB
4124static GenOpFunc *gen_op_eciwx[] = {
4125 &gen_op_eciwx_user,
111bfab3 4126 &gen_op_eciwx_le_user,
d9bce9d9
JM
4127 &gen_op_eciwx_64_user,
4128 &gen_op_eciwx_le_64_user,
2857068e
JM
4129 &gen_op_eciwx_kernel,
4130 &gen_op_eciwx_le_kernel,
d9bce9d9
JM
4131 &gen_op_eciwx_64_kernel,
4132 &gen_op_eciwx_le_64_kernel,
2857068e
JM
4133#if defined(TARGET_PPC64H)
4134 &gen_op_eciwx_hypv,
4135 &gen_op_eciwx_le_hypv,
4136 &gen_op_eciwx_64_hypv,
4137 &gen_op_eciwx_le_64_hypv,
4138#endif
9a64fbe4
FB
4139};
4140static GenOpFunc *gen_op_ecowx[] = {
4141 &gen_op_ecowx_user,
111bfab3 4142 &gen_op_ecowx_le_user,
d9bce9d9
JM
4143 &gen_op_ecowx_64_user,
4144 &gen_op_ecowx_le_64_user,
2857068e
JM
4145 &gen_op_ecowx_kernel,
4146 &gen_op_ecowx_le_kernel,
d9bce9d9
JM
4147 &gen_op_ecowx_64_kernel,
4148 &gen_op_ecowx_le_64_kernel,
2857068e
JM
4149#if defined(TARGET_PPC64H)
4150 &gen_op_ecowx_hypv,
4151 &gen_op_ecowx_le_hypv,
4152 &gen_op_ecowx_64_hypv,
4153 &gen_op_ecowx_le_64_hypv,
9a64fbe4 4154#endif
d9bce9d9
JM
4155};
4156#else
2857068e 4157/* Full system - 32 bits mode */
d9bce9d9
JM
4158static GenOpFunc *gen_op_eciwx[] = {
4159 &gen_op_eciwx_user,
4160 &gen_op_eciwx_le_user,
4161 &gen_op_eciwx_kernel,
4162 &gen_op_eciwx_le_kernel,
4163};
4164static GenOpFunc *gen_op_ecowx[] = {
4165 &gen_op_ecowx_user,
4166 &gen_op_ecowx_le_user,
4167 &gen_op_ecowx_kernel,
4168 &gen_op_ecowx_le_kernel,
4169};
4170#endif
4171#endif
9a64fbe4 4172
111bfab3 4173/* eciwx */
79aceca5
FB
4174GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
4175{
9a64fbe4 4176 /* Should check EAR[E] & alignment ! */
76a66253
JM
4177 gen_addr_reg_index(ctx);
4178 op_eciwx();
4179 gen_op_store_T0_gpr(rD(ctx->opcode));
4180}
4181
4182/* ecowx */
4183GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
4184{
4185 /* Should check EAR[E] & alignment ! */
4186 gen_addr_reg_index(ctx);
4187 gen_op_load_gpr_T1(rS(ctx->opcode));
4188 op_ecowx();
4189}
4190
4191/* PowerPC 601 specific instructions */
4192/* abs - abs. */
4193GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
4194{
4195 gen_op_load_gpr_T0(rA(ctx->opcode));
4196 gen_op_POWER_abs();
4197 gen_op_store_T0_gpr(rD(ctx->opcode));
4198 if (unlikely(Rc(ctx->opcode) != 0))
4199 gen_set_Rc0(ctx);
4200}
4201
4202/* abso - abso. */
4203GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
4204{
4205 gen_op_load_gpr_T0(rA(ctx->opcode));
4206 gen_op_POWER_abso();
4207 gen_op_store_T0_gpr(rD(ctx->opcode));
4208 if (unlikely(Rc(ctx->opcode) != 0))
4209 gen_set_Rc0(ctx);
4210}
4211
4212/* clcs */
a750fc0b 4213GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
76a66253
JM
4214{
4215 gen_op_load_gpr_T0(rA(ctx->opcode));
4216 gen_op_POWER_clcs();
4217 gen_op_store_T0_gpr(rD(ctx->opcode));
4218}
4219
4220/* div - div. */
4221GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
4222{
4223 gen_op_load_gpr_T0(rA(ctx->opcode));
4224 gen_op_load_gpr_T1(rB(ctx->opcode));
4225 gen_op_POWER_div();
4226 gen_op_store_T0_gpr(rD(ctx->opcode));
4227 if (unlikely(Rc(ctx->opcode) != 0))
4228 gen_set_Rc0(ctx);
4229}
4230
4231/* divo - divo. */
4232GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
4233{
4234 gen_op_load_gpr_T0(rA(ctx->opcode));
4235 gen_op_load_gpr_T1(rB(ctx->opcode));
4236 gen_op_POWER_divo();
4237 gen_op_store_T0_gpr(rD(ctx->opcode));
4238 if (unlikely(Rc(ctx->opcode) != 0))
4239 gen_set_Rc0(ctx);
4240}
4241
4242/* divs - divs. */
4243GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
4244{
4245 gen_op_load_gpr_T0(rA(ctx->opcode));
4246 gen_op_load_gpr_T1(rB(ctx->opcode));
4247 gen_op_POWER_divs();
4248 gen_op_store_T0_gpr(rD(ctx->opcode));
4249 if (unlikely(Rc(ctx->opcode) != 0))
4250 gen_set_Rc0(ctx);
4251}
4252
4253/* divso - divso. */
4254GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
4255{
4256 gen_op_load_gpr_T0(rA(ctx->opcode));
4257 gen_op_load_gpr_T1(rB(ctx->opcode));
4258 gen_op_POWER_divso();
4259 gen_op_store_T0_gpr(rD(ctx->opcode));
4260 if (unlikely(Rc(ctx->opcode) != 0))
4261 gen_set_Rc0(ctx);
4262}
4263
4264/* doz - doz. */
4265GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
4266{
4267 gen_op_load_gpr_T0(rA(ctx->opcode));
4268 gen_op_load_gpr_T1(rB(ctx->opcode));
4269 gen_op_POWER_doz();
4270 gen_op_store_T0_gpr(rD(ctx->opcode));
4271 if (unlikely(Rc(ctx->opcode) != 0))
4272 gen_set_Rc0(ctx);
4273}
4274
4275/* dozo - dozo. */
4276GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
4277{
4278 gen_op_load_gpr_T0(rA(ctx->opcode));
4279 gen_op_load_gpr_T1(rB(ctx->opcode));
4280 gen_op_POWER_dozo();
4281 gen_op_store_T0_gpr(rD(ctx->opcode));
4282 if (unlikely(Rc(ctx->opcode) != 0))
4283 gen_set_Rc0(ctx);
4284}
4285
4286/* dozi */
4287GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4288{
4289 gen_op_load_gpr_T0(rA(ctx->opcode));
4290 gen_op_set_T1(SIMM(ctx->opcode));
4291 gen_op_POWER_doz();
4292 gen_op_store_T0_gpr(rD(ctx->opcode));
4293}
4294
4295/* As lscbx load from memory byte after byte, it's always endian safe */
2857068e 4296#define op_POWER_lscbx(start, ra, rb) \
76a66253
JM
4297(*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
4298#if defined(CONFIG_USER_ONLY)
4299static GenOpFunc3 *gen_op_POWER_lscbx[] = {
4300 &gen_op_POWER_lscbx_raw,
4301 &gen_op_POWER_lscbx_raw,
4302};
4303#else
4304static GenOpFunc3 *gen_op_POWER_lscbx[] = {
4305 &gen_op_POWER_lscbx_user,
4306 &gen_op_POWER_lscbx_user,
4307 &gen_op_POWER_lscbx_kernel,
4308 &gen_op_POWER_lscbx_kernel,
4309};
4310#endif
4311
4312/* lscbx - lscbx. */
4313GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
4314{
4315 int ra = rA(ctx->opcode);
4316 int rb = rB(ctx->opcode);
4317
4318 gen_addr_reg_index(ctx);
4319 if (ra == 0) {
4320 ra = rb;
4321 }
4322 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4323 gen_update_nip(ctx, ctx->nip - 4);
76a66253
JM
4324 gen_op_load_xer_bc();
4325 gen_op_load_xer_cmp();
4326 op_POWER_lscbx(rD(ctx->opcode), ra, rb);
4327 gen_op_store_xer_bc();
4328 if (unlikely(Rc(ctx->opcode) != 0))
4329 gen_set_Rc0(ctx);
4330}
4331
4332/* maskg - maskg. */
4333GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
4334{
4335 gen_op_load_gpr_T0(rS(ctx->opcode));
4336 gen_op_load_gpr_T1(rB(ctx->opcode));
4337 gen_op_POWER_maskg();
4338 gen_op_store_T0_gpr(rA(ctx->opcode));
4339 if (unlikely(Rc(ctx->opcode) != 0))
4340 gen_set_Rc0(ctx);
4341}
4342
4343/* maskir - maskir. */
4344GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
4345{
4346 gen_op_load_gpr_T0(rA(ctx->opcode));
4347 gen_op_load_gpr_T1(rS(ctx->opcode));
4348 gen_op_load_gpr_T2(rB(ctx->opcode));
4349 gen_op_POWER_maskir();
4350 gen_op_store_T0_gpr(rA(ctx->opcode));
4351 if (unlikely(Rc(ctx->opcode) != 0))
4352 gen_set_Rc0(ctx);
4353}
4354
4355/* mul - mul. */
4356GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
4357{
4358 gen_op_load_gpr_T0(rA(ctx->opcode));
4359 gen_op_load_gpr_T1(rB(ctx->opcode));
4360 gen_op_POWER_mul();
4361 gen_op_store_T0_gpr(rD(ctx->opcode));
4362 if (unlikely(Rc(ctx->opcode) != 0))
4363 gen_set_Rc0(ctx);
4364}
4365
4366/* mulo - mulo. */
4367GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
4368{
4369 gen_op_load_gpr_T0(rA(ctx->opcode));
4370 gen_op_load_gpr_T1(rB(ctx->opcode));
4371 gen_op_POWER_mulo();
4372 gen_op_store_T0_gpr(rD(ctx->opcode));
4373 if (unlikely(Rc(ctx->opcode) != 0))
4374 gen_set_Rc0(ctx);
4375}
4376
4377/* nabs - nabs. */
4378GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
4379{
4380 gen_op_load_gpr_T0(rA(ctx->opcode));
4381 gen_op_POWER_nabs();
4382 gen_op_store_T0_gpr(rD(ctx->opcode));
4383 if (unlikely(Rc(ctx->opcode) != 0))
4384 gen_set_Rc0(ctx);
4385}
4386
4387/* nabso - nabso. */
4388GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
4389{
4390 gen_op_load_gpr_T0(rA(ctx->opcode));
4391 gen_op_POWER_nabso();
4392 gen_op_store_T0_gpr(rD(ctx->opcode));
4393 if (unlikely(Rc(ctx->opcode) != 0))
4394 gen_set_Rc0(ctx);
4395}
4396
4397/* rlmi - rlmi. */
4398GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4399{
4400 uint32_t mb, me;
4401
4402 mb = MB(ctx->opcode);
4403 me = ME(ctx->opcode);
4404 gen_op_load_gpr_T0(rS(ctx->opcode));
4405 gen_op_load_gpr_T1(rA(ctx->opcode));
4406 gen_op_load_gpr_T2(rB(ctx->opcode));
4407 gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
4408 gen_op_store_T0_gpr(rA(ctx->opcode));
4409 if (unlikely(Rc(ctx->opcode) != 0))
4410 gen_set_Rc0(ctx);
4411}
4412
4413/* rrib - rrib. */
4414GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
4415{
4416 gen_op_load_gpr_T0(rS(ctx->opcode));
4417 gen_op_load_gpr_T1(rA(ctx->opcode));
4418 gen_op_load_gpr_T2(rB(ctx->opcode));
4419 gen_op_POWER_rrib();
4420 gen_op_store_T0_gpr(rA(ctx->opcode));
4421 if (unlikely(Rc(ctx->opcode) != 0))
4422 gen_set_Rc0(ctx);
4423}
4424
4425/* sle - sle. */
4426GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
4427{
4428 gen_op_load_gpr_T0(rS(ctx->opcode));
4429 gen_op_load_gpr_T1(rB(ctx->opcode));
4430 gen_op_POWER_sle();
4431 gen_op_store_T0_gpr(rA(ctx->opcode));
4432 if (unlikely(Rc(ctx->opcode) != 0))
4433 gen_set_Rc0(ctx);
4434}
4435
4436/* sleq - sleq. */
4437GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
4438{
4439 gen_op_load_gpr_T0(rS(ctx->opcode));
4440 gen_op_load_gpr_T1(rB(ctx->opcode));
4441 gen_op_POWER_sleq();
4442 gen_op_store_T0_gpr(rA(ctx->opcode));
4443 if (unlikely(Rc(ctx->opcode) != 0))
4444 gen_set_Rc0(ctx);
4445}
4446
4447/* sliq - sliq. */
4448GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
4449{
4450 gen_op_load_gpr_T0(rS(ctx->opcode));
4451 gen_op_set_T1(SH(ctx->opcode));
4452 gen_op_POWER_sle();
4453 gen_op_store_T0_gpr(rA(ctx->opcode));
4454 if (unlikely(Rc(ctx->opcode) != 0))
4455 gen_set_Rc0(ctx);
4456}
4457
4458/* slliq - slliq. */
4459GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
4460{
4461 gen_op_load_gpr_T0(rS(ctx->opcode));
4462 gen_op_set_T1(SH(ctx->opcode));
4463 gen_op_POWER_sleq();
4464 gen_op_store_T0_gpr(rA(ctx->opcode));
4465 if (unlikely(Rc(ctx->opcode) != 0))
4466 gen_set_Rc0(ctx);
4467}
4468
4469/* sllq - sllq. */
4470GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
4471{
4472 gen_op_load_gpr_T0(rS(ctx->opcode));
4473 gen_op_load_gpr_T1(rB(ctx->opcode));
4474 gen_op_POWER_sllq();
4475 gen_op_store_T0_gpr(rA(ctx->opcode));
4476 if (unlikely(Rc(ctx->opcode) != 0))
4477 gen_set_Rc0(ctx);
4478}
4479
4480/* slq - slq. */
4481GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
4482{
4483 gen_op_load_gpr_T0(rS(ctx->opcode));
4484 gen_op_load_gpr_T1(rB(ctx->opcode));
4485 gen_op_POWER_slq();
4486 gen_op_store_T0_gpr(rA(ctx->opcode));
4487 if (unlikely(Rc(ctx->opcode) != 0))
4488 gen_set_Rc0(ctx);
4489}
4490
d9bce9d9 4491/* sraiq - sraiq. */
76a66253
JM
4492GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
4493{
4494 gen_op_load_gpr_T0(rS(ctx->opcode));
4495 gen_op_set_T1(SH(ctx->opcode));
4496 gen_op_POWER_sraq();
4497 gen_op_store_T0_gpr(rA(ctx->opcode));
4498 if (unlikely(Rc(ctx->opcode) != 0))
4499 gen_set_Rc0(ctx);
4500}
4501
4502/* sraq - sraq. */
4503GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
4504{
4505 gen_op_load_gpr_T0(rS(ctx->opcode));
4506 gen_op_load_gpr_T1(rB(ctx->opcode));
4507 gen_op_POWER_sraq();
4508 gen_op_store_T0_gpr(rA(ctx->opcode));
4509 if (unlikely(Rc(ctx->opcode) != 0))
4510 gen_set_Rc0(ctx);
4511}
4512
4513/* sre - sre. */
4514GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
4515{
4516 gen_op_load_gpr_T0(rS(ctx->opcode));
4517 gen_op_load_gpr_T1(rB(ctx->opcode));
4518 gen_op_POWER_sre();
4519 gen_op_store_T0_gpr(rA(ctx->opcode));
4520 if (unlikely(Rc(ctx->opcode) != 0))
4521 gen_set_Rc0(ctx);
4522}
4523
4524/* srea - srea. */
4525GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
4526{
4527 gen_op_load_gpr_T0(rS(ctx->opcode));
4528 gen_op_load_gpr_T1(rB(ctx->opcode));
4529 gen_op_POWER_srea();
4530 gen_op_store_T0_gpr(rA(ctx->opcode));
4531 if (unlikely(Rc(ctx->opcode) != 0))
4532 gen_set_Rc0(ctx);
4533}
4534
4535/* sreq */
4536GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
4537{
4538 gen_op_load_gpr_T0(rS(ctx->opcode));
4539 gen_op_load_gpr_T1(rB(ctx->opcode));
4540 gen_op_POWER_sreq();
4541 gen_op_store_T0_gpr(rA(ctx->opcode));
4542 if (unlikely(Rc(ctx->opcode) != 0))
4543 gen_set_Rc0(ctx);
4544}
4545
4546/* sriq */
4547GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
4548{
4549 gen_op_load_gpr_T0(rS(ctx->opcode));
4550 gen_op_set_T1(SH(ctx->opcode));
4551 gen_op_POWER_srq();
4552 gen_op_store_T0_gpr(rA(ctx->opcode));
4553 if (unlikely(Rc(ctx->opcode) != 0))
4554 gen_set_Rc0(ctx);
4555}
4556
4557/* srliq */
4558GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
4559{
4560 gen_op_load_gpr_T0(rS(ctx->opcode));
4561 gen_op_load_gpr_T1(rB(ctx->opcode));
4562 gen_op_set_T1(SH(ctx->opcode));
4563 gen_op_POWER_srlq();
4564 gen_op_store_T0_gpr(rA(ctx->opcode));
4565 if (unlikely(Rc(ctx->opcode) != 0))
4566 gen_set_Rc0(ctx);
4567}
4568
4569/* srlq */
4570GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
4571{
4572 gen_op_load_gpr_T0(rS(ctx->opcode));
4573 gen_op_load_gpr_T1(rB(ctx->opcode));
4574 gen_op_POWER_srlq();
4575 gen_op_store_T0_gpr(rA(ctx->opcode));
4576 if (unlikely(Rc(ctx->opcode) != 0))
4577 gen_set_Rc0(ctx);
4578}
4579
4580/* srq */
4581GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
4582{
4583 gen_op_load_gpr_T0(rS(ctx->opcode));
4584 gen_op_load_gpr_T1(rB(ctx->opcode));
4585 gen_op_POWER_srq();
4586 gen_op_store_T0_gpr(rA(ctx->opcode));
4587 if (unlikely(Rc(ctx->opcode) != 0))
4588 gen_set_Rc0(ctx);
4589}
4590
4591/* PowerPC 602 specific instructions */
4592/* dsa */
4593GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
4594{
4595 /* XXX: TODO */
e1833e1f 4596 GEN_EXCP_INVAL(ctx);
76a66253
JM
4597}
4598
4599/* esa */
4600GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
4601{
4602 /* XXX: TODO */
e1833e1f 4603 GEN_EXCP_INVAL(ctx);
76a66253
JM
4604}
4605
4606/* mfrom */
4607GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
4608{
4609#if defined(CONFIG_USER_ONLY)
e1833e1f 4610 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4611#else
4612 if (unlikely(!ctx->supervisor)) {
e1833e1f 4613 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4614 return;
4615 }
4616 gen_op_load_gpr_T0(rA(ctx->opcode));
4617 gen_op_602_mfrom();
4618 gen_op_store_T0_gpr(rD(ctx->opcode));
4619#endif
4620}
4621
4622/* 602 - 603 - G2 TLB management */
4623/* tlbld */
7dbe11ac 4624GEN_HANDLER(tlbld_6xx, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
76a66253
JM
4625{
4626#if defined(CONFIG_USER_ONLY)
e1833e1f 4627 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4628#else
4629 if (unlikely(!ctx->supervisor)) {
e1833e1f 4630 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4631 return;
4632 }
4633 gen_op_load_gpr_T0(rB(ctx->opcode));
4634 gen_op_6xx_tlbld();
76a66253
JM
4635#endif
4636}
4637
4638/* tlbli */
7dbe11ac 4639GEN_HANDLER(tlbli_6xx, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
76a66253
JM
4640{
4641#if defined(CONFIG_USER_ONLY)
e1833e1f 4642 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4643#else
4644 if (unlikely(!ctx->supervisor)) {
e1833e1f 4645 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4646 return;
4647 }
4648 gen_op_load_gpr_T0(rB(ctx->opcode));
4649 gen_op_6xx_tlbli();
76a66253
JM
4650#endif
4651}
4652
7dbe11ac
JM
4653/* 74xx TLB management */
4654/* tlbld */
4655GEN_HANDLER(tlbld_74xx, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
4656{
4657#if defined(CONFIG_USER_ONLY)
4658 GEN_EXCP_PRIVOPC(ctx);
4659#else
4660 if (unlikely(!ctx->supervisor)) {
4661 GEN_EXCP_PRIVOPC(ctx);
4662 return;
4663 }
4664 gen_op_load_gpr_T0(rB(ctx->opcode));
4665 gen_op_74xx_tlbld();
4666#endif
4667}
4668
4669/* tlbli */
4670GEN_HANDLER(tlbli_74xx, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
4671{
4672#if defined(CONFIG_USER_ONLY)
4673 GEN_EXCP_PRIVOPC(ctx);
4674#else
4675 if (unlikely(!ctx->supervisor)) {
4676 GEN_EXCP_PRIVOPC(ctx);
4677 return;
4678 }
4679 gen_op_load_gpr_T0(rB(ctx->opcode));
4680 gen_op_74xx_tlbli();
4681#endif
4682}
4683
76a66253
JM
4684/* POWER instructions not in PowerPC 601 */
4685/* clf */
4686GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
4687{
4688 /* Cache line flush: implemented as no-op */
4689}
4690
4691/* cli */
4692GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
4693{
7f75ffd3 4694 /* Cache line invalidate: privileged and treated as no-op */
76a66253 4695#if defined(CONFIG_USER_ONLY)
e1833e1f 4696 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4697#else
4698 if (unlikely(!ctx->supervisor)) {
e1833e1f 4699 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4700 return;
4701 }
4702#endif
4703}
4704
4705/* dclst */
4706GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
4707{
4708 /* Data cache line store: treated as no-op */
4709}
4710
4711GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
4712{
4713#if defined(CONFIG_USER_ONLY)
e1833e1f 4714 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4715#else
4716 if (unlikely(!ctx->supervisor)) {
e1833e1f 4717 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4718 return;
4719 }
4720 int ra = rA(ctx->opcode);
4721 int rd = rD(ctx->opcode);
4722
4723 gen_addr_reg_index(ctx);
4724 gen_op_POWER_mfsri();
4725 gen_op_store_T0_gpr(rd);
4726 if (ra != 0 && ra != rd)
4727 gen_op_store_T1_gpr(ra);
4728#endif
4729}
4730
4731GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
4732{
4733#if defined(CONFIG_USER_ONLY)
e1833e1f 4734 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4735#else
4736 if (unlikely(!ctx->supervisor)) {
e1833e1f 4737 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4738 return;
4739 }
4740 gen_addr_reg_index(ctx);
4741 gen_op_POWER_rac();
4742 gen_op_store_T0_gpr(rD(ctx->opcode));
4743#endif
4744}
4745
4746GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
4747{
4748#if defined(CONFIG_USER_ONLY)
e1833e1f 4749 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4750#else
4751 if (unlikely(!ctx->supervisor)) {
e1833e1f 4752 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4753 return;
4754 }
4755 gen_op_POWER_rfsvc();
e1833e1f 4756 GEN_SYNC(ctx);
76a66253
JM
4757#endif
4758}
4759
4760/* svc is not implemented for now */
4761
4762/* POWER2 specific instructions */
4763/* Quad manipulation (load/store two floats at a time) */
4764#define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
4765#define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
4766#if defined(CONFIG_USER_ONLY)
4767static GenOpFunc *gen_op_POWER2_lfq[] = {
4768 &gen_op_POWER2_lfq_le_raw,
4769 &gen_op_POWER2_lfq_raw,
4770};
4771static GenOpFunc *gen_op_POWER2_stfq[] = {
4772 &gen_op_POWER2_stfq_le_raw,
4773 &gen_op_POWER2_stfq_raw,
4774};
4775#else
4776static GenOpFunc *gen_op_POWER2_lfq[] = {
4777 &gen_op_POWER2_lfq_le_user,
4778 &gen_op_POWER2_lfq_user,
4779 &gen_op_POWER2_lfq_le_kernel,
4780 &gen_op_POWER2_lfq_kernel,
4781};
4782static GenOpFunc *gen_op_POWER2_stfq[] = {
4783 &gen_op_POWER2_stfq_le_user,
4784 &gen_op_POWER2_stfq_user,
4785 &gen_op_POWER2_stfq_le_kernel,
4786 &gen_op_POWER2_stfq_kernel,
4787};
4788#endif
4789
4790/* lfq */
4791GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4792{
4793 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4794 gen_update_nip(ctx, ctx->nip - 4);
9d53c753 4795 gen_addr_imm_index(ctx, 0);
76a66253
JM
4796 op_POWER2_lfq();
4797 gen_op_store_FT0_fpr(rD(ctx->opcode));
4798 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4799}
4800
4801/* lfqu */
4802GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4803{
4804 int ra = rA(ctx->opcode);
4805
4806 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4807 gen_update_nip(ctx, ctx->nip - 4);
9d53c753 4808 gen_addr_imm_index(ctx, 0);
76a66253
JM
4809 op_POWER2_lfq();
4810 gen_op_store_FT0_fpr(rD(ctx->opcode));
4811 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4812 if (ra != 0)
4813 gen_op_store_T0_gpr(ra);
4814}
4815
4816/* lfqux */
4817GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
4818{
4819 int ra = rA(ctx->opcode);
4820
4821 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4822 gen_update_nip(ctx, ctx->nip - 4);
76a66253
JM
4823 gen_addr_reg_index(ctx);
4824 op_POWER2_lfq();
4825 gen_op_store_FT0_fpr(rD(ctx->opcode));
4826 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4827 if (ra != 0)
4828 gen_op_store_T0_gpr(ra);
4829}
4830
4831/* lfqx */
4832GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
4833{
4834 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4835 gen_update_nip(ctx, ctx->nip - 4);
76a66253
JM
4836 gen_addr_reg_index(ctx);
4837 op_POWER2_lfq();
4838 gen_op_store_FT0_fpr(rD(ctx->opcode));
4839 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4840}
4841
4842/* stfq */
4843GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4844{
4845 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4846 gen_update_nip(ctx, ctx->nip - 4);
9d53c753 4847 gen_addr_imm_index(ctx, 0);
76a66253
JM
4848 gen_op_load_fpr_FT0(rS(ctx->opcode));
4849 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4850 op_POWER2_stfq();
4851}
4852
4853/* stfqu */
4854GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4855{
4856 int ra = rA(ctx->opcode);
4857
4858 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4859 gen_update_nip(ctx, ctx->nip - 4);
9d53c753 4860 gen_addr_imm_index(ctx, 0);
76a66253
JM
4861 gen_op_load_fpr_FT0(rS(ctx->opcode));
4862 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4863 op_POWER2_stfq();
4864 if (ra != 0)
4865 gen_op_store_T0_gpr(ra);
4866}
4867
4868/* stfqux */
4869GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
4870{
4871 int ra = rA(ctx->opcode);
4872
4873 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4874 gen_update_nip(ctx, ctx->nip - 4);
76a66253
JM
4875 gen_addr_reg_index(ctx);
4876 gen_op_load_fpr_FT0(rS(ctx->opcode));
4877 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4878 op_POWER2_stfq();
4879 if (ra != 0)
4880 gen_op_store_T0_gpr(ra);
4881}
4882
4883/* stfqx */
4884GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
4885{
4886 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4887 gen_update_nip(ctx, ctx->nip - 4);
76a66253
JM
4888 gen_addr_reg_index(ctx);
4889 gen_op_load_fpr_FT0(rS(ctx->opcode));
4890 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4891 op_POWER2_stfq();
4892}
4893
4894/* BookE specific instructions */
2662a059 4895/* XXX: not implemented on 440 ? */
a750fc0b 4896GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE_EXT)
76a66253
JM
4897{
4898 /* XXX: TODO */
e1833e1f 4899 GEN_EXCP_INVAL(ctx);
76a66253
JM
4900}
4901
2662a059 4902/* XXX: not implemented on 440 ? */
a750fc0b 4903GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE_EXT)
76a66253
JM
4904{
4905#if defined(CONFIG_USER_ONLY)
e1833e1f 4906 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4907#else
4908 if (unlikely(!ctx->supervisor)) {
e1833e1f 4909 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4910 return;
4911 }
4912 gen_addr_reg_index(ctx);
4913 /* Use the same micro-ops as for tlbie */
d9bce9d9
JM
4914#if defined(TARGET_PPC64)
4915 if (ctx->sf_mode)
4916 gen_op_tlbie_64();
4917 else
4918#endif
4919 gen_op_tlbie();
76a66253
JM
4920#endif
4921}
4922
4923/* All 405 MAC instructions are translated here */
b068d6a7
JM
4924static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
4925 int opc2, int opc3,
4926 int ra, int rb, int rt, int Rc)
76a66253
JM
4927{
4928 gen_op_load_gpr_T0(ra);
4929 gen_op_load_gpr_T1(rb);
4930 switch (opc3 & 0x0D) {
4931 case 0x05:
4932 /* macchw - macchw. - macchwo - macchwo. */
4933 /* macchws - macchws. - macchwso - macchwso. */
4934 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
4935 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
4936 /* mulchw - mulchw. */
4937 gen_op_405_mulchw();
4938 break;
4939 case 0x04:
4940 /* macchwu - macchwu. - macchwuo - macchwuo. */
4941 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
4942 /* mulchwu - mulchwu. */
4943 gen_op_405_mulchwu();
4944 break;
4945 case 0x01:
4946 /* machhw - machhw. - machhwo - machhwo. */
4947 /* machhws - machhws. - machhwso - machhwso. */
4948 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
4949 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
4950 /* mulhhw - mulhhw. */
4951 gen_op_405_mulhhw();
4952 break;
4953 case 0x00:
4954 /* machhwu - machhwu. - machhwuo - machhwuo. */
4955 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
4956 /* mulhhwu - mulhhwu. */
4957 gen_op_405_mulhhwu();
4958 break;
4959 case 0x0D:
4960 /* maclhw - maclhw. - maclhwo - maclhwo. */
4961 /* maclhws - maclhws. - maclhwso - maclhwso. */
4962 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
4963 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
4964 /* mullhw - mullhw. */
4965 gen_op_405_mullhw();
4966 break;
4967 case 0x0C:
4968 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
4969 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
4970 /* mullhwu - mullhwu. */
4971 gen_op_405_mullhwu();
4972 break;
4973 }
4974 if (opc2 & 0x02) {
4975 /* nmultiply-and-accumulate (0x0E) */
4976 gen_op_neg();
4977 }
4978 if (opc2 & 0x04) {
4979 /* (n)multiply-and-accumulate (0x0C - 0x0E) */
4980 gen_op_load_gpr_T2(rt);
4981 gen_op_move_T1_T0();
4982 gen_op_405_add_T0_T2();
4983 }
4984 if (opc3 & 0x10) {
4985 /* Check overflow */
4986 if (opc3 & 0x01)
4987 gen_op_405_check_ov();
4988 else
4989 gen_op_405_check_ovu();
4990 }
4991 if (opc3 & 0x02) {
4992 /* Saturate */
4993 if (opc3 & 0x01)
4994 gen_op_405_check_sat();
4995 else
4996 gen_op_405_check_satu();
4997 }
4998 gen_op_store_T0_gpr(rt);
4999 if (unlikely(Rc) != 0) {
5000 /* Update Rc0 */
5001 gen_set_Rc0(ctx);
5002 }
5003}
5004
a750fc0b
JM
5005#define GEN_MAC_HANDLER(name, opc2, opc3) \
5006GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
76a66253
JM
5007{ \
5008 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5009 rD(ctx->opcode), Rc(ctx->opcode)); \
5010}
5011
5012/* macchw - macchw. */
a750fc0b 5013GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
76a66253 5014/* macchwo - macchwo. */
a750fc0b 5015GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
76a66253 5016/* macchws - macchws. */
a750fc0b 5017GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
76a66253 5018/* macchwso - macchwso. */
a750fc0b 5019GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
76a66253 5020/* macchwsu - macchwsu. */
a750fc0b 5021GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
76a66253 5022/* macchwsuo - macchwsuo. */
a750fc0b 5023GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
76a66253 5024/* macchwu - macchwu. */
a750fc0b 5025GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
76a66253 5026/* macchwuo - macchwuo. */
a750fc0b 5027GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
76a66253 5028/* machhw - machhw. */
a750fc0b 5029GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
76a66253 5030/* machhwo - machhwo. */
a750fc0b 5031GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
76a66253 5032/* machhws - machhws. */
a750fc0b 5033GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
76a66253 5034/* machhwso - machhwso. */
a750fc0b 5035GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
76a66253 5036/* machhwsu - machhwsu. */
a750fc0b 5037GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
76a66253 5038/* machhwsuo - machhwsuo. */
a750fc0b 5039GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
76a66253 5040/* machhwu - machhwu. */
a750fc0b 5041GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
76a66253 5042/* machhwuo - machhwuo. */
a750fc0b 5043GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
76a66253 5044/* maclhw - maclhw. */
a750fc0b 5045GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
76a66253 5046/* maclhwo - maclhwo. */
a750fc0b 5047GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
76a66253 5048/* maclhws - maclhws. */
a750fc0b 5049GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
76a66253 5050/* maclhwso - maclhwso. */
a750fc0b 5051GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
76a66253 5052/* maclhwu - maclhwu. */
a750fc0b 5053GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
76a66253 5054/* maclhwuo - maclhwuo. */
a750fc0b 5055GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
76a66253 5056/* maclhwsu - maclhwsu. */
a750fc0b 5057GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
76a66253 5058/* maclhwsuo - maclhwsuo. */
a750fc0b 5059GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
76a66253 5060/* nmacchw - nmacchw. */
a750fc0b 5061GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
76a66253 5062/* nmacchwo - nmacchwo. */
a750fc0b 5063GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
76a66253 5064/* nmacchws - nmacchws. */
a750fc0b 5065GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
76a66253 5066/* nmacchwso - nmacchwso. */
a750fc0b 5067GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
76a66253 5068/* nmachhw - nmachhw. */
a750fc0b 5069GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
76a66253 5070/* nmachhwo - nmachhwo. */
a750fc0b 5071GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
76a66253 5072/* nmachhws - nmachhws. */
a750fc0b 5073GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
76a66253 5074/* nmachhwso - nmachhwso. */
a750fc0b 5075GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
76a66253 5076/* nmaclhw - nmaclhw. */
a750fc0b 5077GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
76a66253 5078/* nmaclhwo - nmaclhwo. */
a750fc0b 5079GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
76a66253 5080/* nmaclhws - nmaclhws. */
a750fc0b 5081GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
76a66253 5082/* nmaclhwso - nmaclhwso. */
a750fc0b 5083GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
76a66253
JM
5084
5085/* mulchw - mulchw. */
a750fc0b 5086GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
76a66253 5087/* mulchwu - mulchwu. */
a750fc0b 5088GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
76a66253 5089/* mulhhw - mulhhw. */
a750fc0b 5090GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
76a66253 5091/* mulhhwu - mulhhwu. */
a750fc0b 5092GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
76a66253 5093/* mullhw - mullhw. */
a750fc0b 5094GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
76a66253 5095/* mullhwu - mullhwu. */
a750fc0b 5096GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
76a66253
JM
5097
5098/* mfdcr */
5099GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
5100{
5101#if defined(CONFIG_USER_ONLY)
e1833e1f 5102 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5103#else
5104 uint32_t dcrn = SPR(ctx->opcode);
5105
5106 if (unlikely(!ctx->supervisor)) {
e1833e1f 5107 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5108 return;
5109 }
a42bd6cc
JM
5110 gen_op_set_T0(dcrn);
5111 gen_op_load_dcr();
76a66253
JM
5112 gen_op_store_T0_gpr(rD(ctx->opcode));
5113#endif
5114}
5115
5116/* mtdcr */
5117GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
5118{
5119#if defined(CONFIG_USER_ONLY)
e1833e1f 5120 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5121#else
5122 uint32_t dcrn = SPR(ctx->opcode);
5123
5124 if (unlikely(!ctx->supervisor)) {
e1833e1f 5125 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5126 return;
5127 }
a42bd6cc
JM
5128 gen_op_set_T0(dcrn);
5129 gen_op_load_gpr_T1(rS(ctx->opcode));
5130 gen_op_store_dcr();
5131#endif
5132}
5133
5134/* mfdcrx */
2662a059 5135/* XXX: not implemented on 440 ? */
a750fc0b 5136GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_BOOKE_EXT)
a42bd6cc
JM
5137{
5138#if defined(CONFIG_USER_ONLY)
e1833e1f 5139 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5140#else
5141 if (unlikely(!ctx->supervisor)) {
e1833e1f 5142 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5143 return;
5144 }
5145 gen_op_load_gpr_T0(rA(ctx->opcode));
5146 gen_op_load_dcr();
5147 gen_op_store_T0_gpr(rD(ctx->opcode));
a750fc0b 5148 /* Note: Rc update flag set leads to undefined state of Rc0 */
a42bd6cc
JM
5149#endif
5150}
5151
5152/* mtdcrx */
2662a059 5153/* XXX: not implemented on 440 ? */
a750fc0b 5154GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_BOOKE_EXT)
a42bd6cc
JM
5155{
5156#if defined(CONFIG_USER_ONLY)
e1833e1f 5157 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5158#else
5159 if (unlikely(!ctx->supervisor)) {
e1833e1f 5160 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5161 return;
5162 }
5163 gen_op_load_gpr_T0(rA(ctx->opcode));
5164 gen_op_load_gpr_T1(rS(ctx->opcode));
5165 gen_op_store_dcr();
a750fc0b 5166 /* Note: Rc update flag set leads to undefined state of Rc0 */
76a66253
JM
5167#endif
5168}
5169
a750fc0b
JM
5170/* mfdcrux (PPC 460) : user-mode access to DCR */
5171GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
5172{
5173 gen_op_load_gpr_T0(rA(ctx->opcode));
5174 gen_op_load_dcr();
5175 gen_op_store_T0_gpr(rD(ctx->opcode));
5176 /* Note: Rc update flag set leads to undefined state of Rc0 */
5177}
5178
5179/* mtdcrux (PPC 460) : user-mode access to DCR */
5180GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
5181{
5182 gen_op_load_gpr_T0(rA(ctx->opcode));
5183 gen_op_load_gpr_T1(rS(ctx->opcode));
5184 gen_op_store_dcr();
5185 /* Note: Rc update flag set leads to undefined state of Rc0 */
5186}
5187
76a66253
JM
5188/* dccci */
5189GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
5190{
5191#if defined(CONFIG_USER_ONLY)
e1833e1f 5192 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5193#else
5194 if (unlikely(!ctx->supervisor)) {
e1833e1f 5195 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5196 return;
5197 }
5198 /* interpreted as no-op */
5199#endif
5200}
5201
5202/* dcread */
5203GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
5204{
5205#if defined(CONFIG_USER_ONLY)
e1833e1f 5206 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5207#else
5208 if (unlikely(!ctx->supervisor)) {
e1833e1f 5209 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5210 return;
5211 }
5212 gen_addr_reg_index(ctx);
5213 op_ldst(lwz);
5214 gen_op_store_T0_gpr(rD(ctx->opcode));
5215#endif
5216}
5217
5218/* icbt */
2662a059 5219GEN_HANDLER(icbt_40x, 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
76a66253
JM
5220{
5221 /* interpreted as no-op */
5222 /* XXX: specification say this is treated as a load by the MMU
5223 * but does not generate any exception
5224 */
5225}
5226
5227/* iccci */
5228GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
5229{
5230#if defined(CONFIG_USER_ONLY)
e1833e1f 5231 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5232#else
5233 if (unlikely(!ctx->supervisor)) {
e1833e1f 5234 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5235 return;
5236 }
5237 /* interpreted as no-op */
5238#endif
5239}
5240
5241/* icread */
5242GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
5243{
5244#if defined(CONFIG_USER_ONLY)
e1833e1f 5245 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5246#else
5247 if (unlikely(!ctx->supervisor)) {
e1833e1f 5248 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5249 return;
5250 }
5251 /* interpreted as no-op */
5252#endif
5253}
5254
5255/* rfci (supervisor only) */
a42bd6cc
JM
5256GEN_HANDLER(rfci_40x, 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
5257{
5258#if defined(CONFIG_USER_ONLY)
e1833e1f 5259 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5260#else
5261 if (unlikely(!ctx->supervisor)) {
e1833e1f 5262 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5263 return;
5264 }
5265 /* Restore CPU state */
5266 gen_op_40x_rfci();
e1833e1f 5267 GEN_SYNC(ctx);
a42bd6cc
JM
5268#endif
5269}
5270
5271GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
5272{
5273#if defined(CONFIG_USER_ONLY)
e1833e1f 5274 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5275#else
5276 if (unlikely(!ctx->supervisor)) {
e1833e1f 5277 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5278 return;
5279 }
5280 /* Restore CPU state */
5281 gen_op_rfci();
e1833e1f 5282 GEN_SYNC(ctx);
a42bd6cc
JM
5283#endif
5284}
5285
5286/* BookE specific */
2662a059 5287/* XXX: not implemented on 440 ? */
a750fc0b 5288GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE_EXT)
76a66253
JM
5289{
5290#if defined(CONFIG_USER_ONLY)
e1833e1f 5291 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5292#else
5293 if (unlikely(!ctx->supervisor)) {
e1833e1f 5294 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5295 return;
5296 }
5297 /* Restore CPU state */
a42bd6cc 5298 gen_op_rfdi();
e1833e1f 5299 GEN_SYNC(ctx);
76a66253
JM
5300#endif
5301}
5302
2662a059 5303/* XXX: not implemented on 440 ? */
a750fc0b 5304GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
a42bd6cc
JM
5305{
5306#if defined(CONFIG_USER_ONLY)
e1833e1f 5307 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5308#else
5309 if (unlikely(!ctx->supervisor)) {
e1833e1f 5310 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5311 return;
5312 }
5313 /* Restore CPU state */
5314 gen_op_rfmci();
e1833e1f 5315 GEN_SYNC(ctx);
a42bd6cc
JM
5316#endif
5317}
5eb7995e 5318
d9bce9d9 5319/* TLB management - PowerPC 405 implementation */
76a66253 5320/* tlbre */
a750fc0b 5321GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
76a66253
JM
5322{
5323#if defined(CONFIG_USER_ONLY)
e1833e1f 5324 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5325#else
5326 if (unlikely(!ctx->supervisor)) {
e1833e1f 5327 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5328 return;
5329 }
5330 switch (rB(ctx->opcode)) {
5331 case 0:
9a64fbe4 5332 gen_op_load_gpr_T0(rA(ctx->opcode));
76a66253
JM
5333 gen_op_4xx_tlbre_hi();
5334 gen_op_store_T0_gpr(rD(ctx->opcode));
5335 break;
5336 case 1:
5337 gen_op_load_gpr_T0(rA(ctx->opcode));
5338 gen_op_4xx_tlbre_lo();
5339 gen_op_store_T0_gpr(rD(ctx->opcode));
5340 break;
5341 default:
e1833e1f 5342 GEN_EXCP_INVAL(ctx);
76a66253 5343 break;
9a64fbe4 5344 }
76a66253
JM
5345#endif
5346}
5347
d9bce9d9 5348/* tlbsx - tlbsx. */
a750fc0b 5349GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
76a66253
JM
5350{
5351#if defined(CONFIG_USER_ONLY)
e1833e1f 5352 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5353#else
5354 if (unlikely(!ctx->supervisor)) {
e1833e1f 5355 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5356 return;
5357 }
5358 gen_addr_reg_index(ctx);
daf4f96e 5359 gen_op_4xx_tlbsx();
76a66253 5360 if (Rc(ctx->opcode))
daf4f96e 5361 gen_op_4xx_tlbsx_check();
9a64fbe4 5362 gen_op_store_T0_gpr(rD(ctx->opcode));
76a66253 5363#endif
79aceca5
FB
5364}
5365
76a66253 5366/* tlbwe */
a750fc0b 5367GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
79aceca5 5368{
76a66253 5369#if defined(CONFIG_USER_ONLY)
e1833e1f 5370 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5371#else
5372 if (unlikely(!ctx->supervisor)) {
e1833e1f 5373 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5374 return;
5375 }
5376 switch (rB(ctx->opcode)) {
5377 case 0:
9a64fbe4 5378 gen_op_load_gpr_T0(rA(ctx->opcode));
76a66253
JM
5379 gen_op_load_gpr_T1(rS(ctx->opcode));
5380 gen_op_4xx_tlbwe_hi();
5381 break;
5382 case 1:
5383 gen_op_load_gpr_T0(rA(ctx->opcode));
5384 gen_op_load_gpr_T1(rS(ctx->opcode));
5385 gen_op_4xx_tlbwe_lo();
5386 break;
5387 default:
e1833e1f 5388 GEN_EXCP_INVAL(ctx);
76a66253 5389 break;
9a64fbe4 5390 }
76a66253
JM
5391#endif
5392}
5393
a4bb6c3e 5394/* TLB management - PowerPC 440 implementation */
5eb7995e 5395/* tlbre */
a4bb6c3e 5396GEN_HANDLER(tlbre_440, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5eb7995e
JM
5397{
5398#if defined(CONFIG_USER_ONLY)
e1833e1f 5399 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5400#else
5401 if (unlikely(!ctx->supervisor)) {
e1833e1f 5402 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5403 return;
5404 }
5405 switch (rB(ctx->opcode)) {
5406 case 0:
5eb7995e 5407 case 1:
5eb7995e
JM
5408 case 2:
5409 gen_op_load_gpr_T0(rA(ctx->opcode));
a4bb6c3e 5410 gen_op_440_tlbre(rB(ctx->opcode));
5eb7995e
JM
5411 gen_op_store_T0_gpr(rD(ctx->opcode));
5412 break;
5413 default:
e1833e1f 5414 GEN_EXCP_INVAL(ctx);
5eb7995e
JM
5415 break;
5416 }
5417#endif
5418}
5419
5420/* tlbsx - tlbsx. */
a4bb6c3e 5421GEN_HANDLER(tlbsx_440, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5eb7995e
JM
5422{
5423#if defined(CONFIG_USER_ONLY)
e1833e1f 5424 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5425#else
5426 if (unlikely(!ctx->supervisor)) {
e1833e1f 5427 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5428 return;
5429 }
5430 gen_addr_reg_index(ctx);
daf4f96e 5431 gen_op_440_tlbsx();
5eb7995e 5432 if (Rc(ctx->opcode))
daf4f96e 5433 gen_op_4xx_tlbsx_check();
5eb7995e
JM
5434 gen_op_store_T0_gpr(rD(ctx->opcode));
5435#endif
5436}
5437
5438/* tlbwe */
a4bb6c3e 5439GEN_HANDLER(tlbwe_440, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5eb7995e
JM
5440{
5441#if defined(CONFIG_USER_ONLY)
e1833e1f 5442 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5443#else
5444 if (unlikely(!ctx->supervisor)) {
e1833e1f 5445 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5446 return;
5447 }
5448 switch (rB(ctx->opcode)) {
5449 case 0:
5eb7995e 5450 case 1:
5eb7995e
JM
5451 case 2:
5452 gen_op_load_gpr_T0(rA(ctx->opcode));
5453 gen_op_load_gpr_T1(rS(ctx->opcode));
a4bb6c3e 5454 gen_op_440_tlbwe(rB(ctx->opcode));
5eb7995e
JM
5455 break;
5456 default:
e1833e1f 5457 GEN_EXCP_INVAL(ctx);
5eb7995e
JM
5458 break;
5459 }
5460#endif
5461}
5462
76a66253
JM
5463/* wrtee */
5464GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
5465{
5466#if defined(CONFIG_USER_ONLY)
e1833e1f 5467 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5468#else
5469 if (unlikely(!ctx->supervisor)) {
e1833e1f 5470 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5471 return;
5472 }
5473 gen_op_load_gpr_T0(rD(ctx->opcode));
a42bd6cc 5474 gen_op_wrte();
dee96f6c
JM
5475 /* Stop translation to have a chance to raise an exception
5476 * if we just set msr_ee to 1
5477 */
e1833e1f 5478 GEN_STOP(ctx);
76a66253
JM
5479#endif
5480}
5481
5482/* wrteei */
5483GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON)
5484{
5485#if defined(CONFIG_USER_ONLY)
e1833e1f 5486 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5487#else
5488 if (unlikely(!ctx->supervisor)) {
e1833e1f 5489 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5490 return;
5491 }
5492 gen_op_set_T0(ctx->opcode & 0x00010000);
a42bd6cc 5493 gen_op_wrte();
dee96f6c
JM
5494 /* Stop translation to have a chance to raise an exception
5495 * if we just set msr_ee to 1
5496 */
e1833e1f 5497 GEN_STOP(ctx);
76a66253
JM
5498#endif
5499}
5500
08e46e54 5501/* PowerPC 440 specific instructions */
76a66253
JM
5502/* dlmzb */
5503GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
5504{
5505 gen_op_load_gpr_T0(rS(ctx->opcode));
5506 gen_op_load_gpr_T1(rB(ctx->opcode));
5507 gen_op_440_dlmzb();
5508 gen_op_store_T0_gpr(rA(ctx->opcode));
5509 gen_op_store_xer_bc();
5510 if (Rc(ctx->opcode)) {
5511 gen_op_440_dlmzb_update_Rc();
5512 gen_op_store_T0_crf(0);
5513 }
5514}
5515
5516/* mbar replaces eieio on 440 */
5517GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
5518{
5519 /* interpreted as no-op */
5520}
5521
5522/* msync replaces sync on 440 */
0db1b20e 5523GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
76a66253
JM
5524{
5525 /* interpreted as no-op */
5526}
5527
5528/* icbt */
5529GEN_HANDLER(icbt_440, 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
5530{
5531 /* interpreted as no-op */
5532 /* XXX: specification say this is treated as a load by the MMU
5533 * but does not generate any exception
5534 */
79aceca5
FB
5535}
5536
a9d9eb8f
JM
5537/*** Altivec vector extension ***/
5538/* Altivec registers moves */
5539GEN32(gen_op_load_avr_A0, gen_op_load_avr_A0_avr);
5540GEN32(gen_op_load_avr_A1, gen_op_load_avr_A1_avr);
5541GEN32(gen_op_load_avr_A2, gen_op_load_avr_A2_avr);
5542
5543GEN32(gen_op_store_A0_avr, gen_op_store_A0_avr_avr);
5544GEN32(gen_op_store_A1_avr, gen_op_store_A1_avr_avr);
5545#if 0 // unused
5546GEN32(gen_op_store_A2_avr, gen_op_store_A2_avr_avr);
5547#endif
5548
5549#define op_vr_ldst(name) (*gen_op_##name[ctx->mem_idx])()
5550#if defined(CONFIG_USER_ONLY)
5551#if defined(TARGET_PPC64)
5552/* User-mode only - 64 bits mode */
5553#define OP_VR_LD_TABLE(name) \
5554static GenOpFunc *gen_op_vr_l##name[] = { \
5555 &gen_op_vr_l##name##_raw, \
5556 &gen_op_vr_l##name##_le_raw, \
5557 &gen_op_vr_l##name##_64_raw, \
5558 &gen_op_vr_l##name##_le_64_raw, \
5559};
5560#define OP_VR_ST_TABLE(name) \
5561static GenOpFunc *gen_op_vr_st##name[] = { \
5562 &gen_op_vr_st##name##_raw, \
5563 &gen_op_vr_st##name##_le_raw, \
5564 &gen_op_vr_st##name##_64_raw, \
5565 &gen_op_vr_st##name##_le_64_raw, \
5566};
5567#else /* defined(TARGET_PPC64) */
5568/* User-mode only - 32 bits mode */
5569#define OP_VR_LD_TABLE(name) \
5570static GenOpFunc *gen_op_vr_l##name[] = { \
5571 &gen_op_vr_l##name##_raw, \
5572 &gen_op_vr_l##name##_le_raw, \
5573};
5574#define OP_VR_ST_TABLE(name) \
5575static GenOpFunc *gen_op_vr_st##name[] = { \
5576 &gen_op_vr_st##name##_raw, \
5577 &gen_op_vr_st##name##_le_raw, \
5578};
5579#endif /* defined(TARGET_PPC64) */
5580#else /* defined(CONFIG_USER_ONLY) */
5581#if defined(TARGET_PPC64H)
5582/* Full system with hypervisor mode */
5583#define OP_VR_LD_TABLE(name) \
5584static GenOpFunc *gen_op_vr_l##name[] = { \
5585 &gen_op_vr_l##name##_user, \
5586 &gen_op_vr_l##name##_le_user, \
5587 &gen_op_vr_l##name##_64_user, \
5588 &gen_op_vr_l##name##_le_64_user, \
5589 &gen_op_vr_l##name##_kernel, \
5590 &gen_op_vr_l##name##_le_kernel, \
5591 &gen_op_vr_l##name##_64_kernel, \
5592 &gen_op_vr_l##name##_le_64_kernel, \
5593 &gen_op_vr_l##name##_hypv, \
5594 &gen_op_vr_l##name##_le_hypv, \
5595 &gen_op_vr_l##name##_64_hypv, \
5596 &gen_op_vr_l##name##_le_64_hypv, \
5597};
5598#define OP_VR_ST_TABLE(name) \
5599static GenOpFunc *gen_op_vr_st##name[] = { \
5600 &gen_op_vr_st##name##_user, \
5601 &gen_op_vr_st##name##_le_user, \
5602 &gen_op_vr_st##name##_64_user, \
5603 &gen_op_vr_st##name##_le_64_user, \
5604 &gen_op_vr_st##name##_kernel, \
5605 &gen_op_vr_st##name##_le_kernel, \
5606 &gen_op_vr_st##name##_64_kernel, \
5607 &gen_op_vr_st##name##_le_64_kernel, \
5608 &gen_op_vr_st##name##_hypv, \
5609 &gen_op_vr_st##name##_le_hypv, \
5610 &gen_op_vr_st##name##_64_hypv, \
5611 &gen_op_vr_st##name##_le_64_hypv, \
5612};
5613#elif defined(TARGET_PPC64)
5614/* Full system - 64 bits mode */
5615#define OP_VR_LD_TABLE(name) \
5616static GenOpFunc *gen_op_vr_l##name[] = { \
5617 &gen_op_vr_l##name##_user, \
5618 &gen_op_vr_l##name##_le_user, \
5619 &gen_op_vr_l##name##_64_user, \
5620 &gen_op_vr_l##name##_le_64_user, \
5621 &gen_op_vr_l##name##_kernel, \
5622 &gen_op_vr_l##name##_le_kernel, \
5623 &gen_op_vr_l##name##_64_kernel, \
5624 &gen_op_vr_l##name##_le_64_kernel, \
5625};
5626#define OP_VR_ST_TABLE(name) \
5627static GenOpFunc *gen_op_vr_st##name[] = { \
5628 &gen_op_vr_st##name##_user, \
5629 &gen_op_vr_st##name##_le_user, \
5630 &gen_op_vr_st##name##_64_user, \
5631 &gen_op_vr_st##name##_le_64_user, \
5632 &gen_op_vr_st##name##_kernel, \
5633 &gen_op_vr_st##name##_le_kernel, \
5634 &gen_op_vr_st##name##_64_kernel, \
5635 &gen_op_vr_st##name##_le_64_kernel, \
5636};
5637#else /* defined(TARGET_PPC64) */
5638/* Full system - 32 bits mode */
5639#define OP_VR_LD_TABLE(name) \
5640static GenOpFunc *gen_op_vr_l##name[] = { \
5641 &gen_op_vr_l##name##_user, \
5642 &gen_op_vr_l##name##_le_user, \
5643 &gen_op_vr_l##name##_kernel, \
5644 &gen_op_vr_l##name##_le_kernel, \
5645};
5646#define OP_VR_ST_TABLE(name) \
5647static GenOpFunc *gen_op_vr_st##name[] = { \
5648 &gen_op_vr_st##name##_user, \
5649 &gen_op_vr_st##name##_le_user, \
5650 &gen_op_vr_st##name##_kernel, \
5651 &gen_op_vr_st##name##_le_kernel, \
5652};
5653#endif /* defined(TARGET_PPC64) */
5654#endif /* defined(CONFIG_USER_ONLY) */
5655
5656#define GEN_VR_LDX(name, opc2, opc3) \
5657GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5658{ \
5659 if (unlikely(!ctx->altivec_enabled)) { \
5660 GEN_EXCP_NO_VR(ctx); \
5661 return; \
5662 } \
5663 gen_addr_reg_index(ctx); \
5664 op_vr_ldst(vr_l##name); \
5665 gen_op_store_A0_avr(rD(ctx->opcode)); \
5666}
5667
5668#define GEN_VR_STX(name, opc2, opc3) \
5669GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5670{ \
5671 if (unlikely(!ctx->altivec_enabled)) { \
5672 GEN_EXCP_NO_VR(ctx); \
5673 return; \
5674 } \
5675 gen_addr_reg_index(ctx); \
5676 gen_op_load_avr_A0(rS(ctx->opcode)); \
5677 op_vr_ldst(vr_st##name); \
5678}
5679
5680OP_VR_LD_TABLE(vx);
5681GEN_VR_LDX(vx, 0x07, 0x03);
5682/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
5683#define gen_op_vr_lvxl gen_op_vr_lvx
5684GEN_VR_LDX(vxl, 0x07, 0x0B);
5685
5686OP_VR_ST_TABLE(vx);
5687GEN_VR_STX(vx, 0x07, 0x07);
5688/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
5689#define gen_op_vr_stvxl gen_op_vr_stvx
5690GEN_VR_STX(vxl, 0x07, 0x0F);
5691
35cdaad6 5692#if defined(TARGET_PPCEMB)
0487d6a8
JM
5693/*** SPE extension ***/
5694
5695/* Register moves */
5696GEN32(gen_op_load_gpr64_T0, gen_op_load_gpr64_T0_gpr);
5697GEN32(gen_op_load_gpr64_T1, gen_op_load_gpr64_T1_gpr);
5698#if 0 // unused
5699GEN32(gen_op_load_gpr64_T2, gen_op_load_gpr64_T2_gpr);
5700#endif
5701
5702GEN32(gen_op_store_T0_gpr64, gen_op_store_T0_gpr64_gpr);
5703GEN32(gen_op_store_T1_gpr64, gen_op_store_T1_gpr64_gpr);
5704#if 0 // unused
5705GEN32(gen_op_store_T2_gpr64, gen_op_store_T2_gpr64_gpr);
5706#endif
5707
5708#define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
5709GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
5710{ \
5711 if (Rc(ctx->opcode)) \
5712 gen_##name1(ctx); \
5713 else \
5714 gen_##name0(ctx); \
5715}
5716
5717/* Handler for undefined SPE opcodes */
b068d6a7 5718static always_inline void gen_speundef (DisasContext *ctx)
0487d6a8 5719{
e1833e1f 5720 GEN_EXCP_INVAL(ctx);
0487d6a8
JM
5721}
5722
5723/* SPE load and stores */
b068d6a7 5724static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
0487d6a8
JM
5725{
5726 target_long simm = rB(ctx->opcode);
5727
5728 if (rA(ctx->opcode) == 0) {
5729 gen_set_T0(simm << sh);
5730 } else {
5731 gen_op_load_gpr_T0(rA(ctx->opcode));
5732 if (likely(simm != 0))
5733 gen_op_addi(simm << sh);
5734 }
5735}
5736
5737#define op_spe_ldst(name) (*gen_op_##name[ctx->mem_idx])()
5738#if defined(CONFIG_USER_ONLY)
5739#if defined(TARGET_PPC64)
2857068e 5740/* User-mode only - 64 bits mode */
0487d6a8
JM
5741#define OP_SPE_LD_TABLE(name) \
5742static GenOpFunc *gen_op_spe_l##name[] = { \
5743 &gen_op_spe_l##name##_raw, \
5744 &gen_op_spe_l##name##_le_raw, \
5745 &gen_op_spe_l##name##_64_raw, \
5746 &gen_op_spe_l##name##_le_64_raw, \
5747};
5748#define OP_SPE_ST_TABLE(name) \
5749static GenOpFunc *gen_op_spe_st##name[] = { \
5750 &gen_op_spe_st##name##_raw, \
5751 &gen_op_spe_st##name##_le_raw, \
5752 &gen_op_spe_st##name##_64_raw, \
5753 &gen_op_spe_st##name##_le_64_raw, \
5754};
5755#else /* defined(TARGET_PPC64) */
2857068e 5756/* User-mode only - 32 bits mode */
0487d6a8
JM
5757#define OP_SPE_LD_TABLE(name) \
5758static GenOpFunc *gen_op_spe_l##name[] = { \
5759 &gen_op_spe_l##name##_raw, \
5760 &gen_op_spe_l##name##_le_raw, \
5761};
5762#define OP_SPE_ST_TABLE(name) \
5763static GenOpFunc *gen_op_spe_st##name[] = { \
5764 &gen_op_spe_st##name##_raw, \
5765 &gen_op_spe_st##name##_le_raw, \
5766};
5767#endif /* defined(TARGET_PPC64) */
5768#else /* defined(CONFIG_USER_ONLY) */
2857068e
JM
5769#if defined(TARGET_PPC64H)
5770/* Full system with hypervisor mode */
0487d6a8
JM
5771#define OP_SPE_LD_TABLE(name) \
5772static GenOpFunc *gen_op_spe_l##name[] = { \
5773 &gen_op_spe_l##name##_user, \
5774 &gen_op_spe_l##name##_le_user, \
0487d6a8
JM
5775 &gen_op_spe_l##name##_64_user, \
5776 &gen_op_spe_l##name##_le_64_user, \
2857068e
JM
5777 &gen_op_spe_l##name##_kernel, \
5778 &gen_op_spe_l##name##_le_kernel, \
0487d6a8
JM
5779 &gen_op_spe_l##name##_64_kernel, \
5780 &gen_op_spe_l##name##_le_64_kernel, \
2857068e
JM
5781 &gen_op_spe_l##name##_hypv, \
5782 &gen_op_spe_l##name##_le_hypv, \
5783 &gen_op_spe_l##name##_64_hypv, \
5784 &gen_op_spe_l##name##_le_64_hypv, \
0487d6a8
JM
5785};
5786#define OP_SPE_ST_TABLE(name) \
5787static GenOpFunc *gen_op_spe_st##name[] = { \
5788 &gen_op_spe_st##name##_user, \
5789 &gen_op_spe_st##name##_le_user, \
2857068e
JM
5790 &gen_op_spe_st##name##_64_user, \
5791 &gen_op_spe_st##name##_le_64_user, \
0487d6a8
JM
5792 &gen_op_spe_st##name##_kernel, \
5793 &gen_op_spe_st##name##_le_kernel, \
2857068e
JM
5794 &gen_op_spe_st##name##_64_kernel, \
5795 &gen_op_spe_st##name##_le_64_kernel, \
5796 &gen_op_spe_st##name##_hypv, \
5797 &gen_op_spe_st##name##_le_hypv, \
5798 &gen_op_spe_st##name##_64_hypv, \
5799 &gen_op_spe_st##name##_le_64_hypv, \
5800};
5801#elif defined(TARGET_PPC64)
5802/* Full system - 64 bits mode */
5803#define OP_SPE_LD_TABLE(name) \
5804static GenOpFunc *gen_op_spe_l##name[] = { \
5805 &gen_op_spe_l##name##_user, \
5806 &gen_op_spe_l##name##_le_user, \
5807 &gen_op_spe_l##name##_64_user, \
5808 &gen_op_spe_l##name##_le_64_user, \
5809 &gen_op_spe_l##name##_kernel, \
5810 &gen_op_spe_l##name##_le_kernel, \
5811 &gen_op_spe_l##name##_64_kernel, \
5812 &gen_op_spe_l##name##_le_64_kernel, \
5813};
5814#define OP_SPE_ST_TABLE(name) \
5815static GenOpFunc *gen_op_spe_st##name[] = { \
5816 &gen_op_spe_st##name##_user, \
5817 &gen_op_spe_st##name##_le_user, \
0487d6a8
JM
5818 &gen_op_spe_st##name##_64_user, \
5819 &gen_op_spe_st##name##_le_64_user, \
2857068e
JM
5820 &gen_op_spe_st##name##_kernel, \
5821 &gen_op_spe_st##name##_le_kernel, \
0487d6a8
JM
5822 &gen_op_spe_st##name##_64_kernel, \
5823 &gen_op_spe_st##name##_le_64_kernel, \
5824};
5825#else /* defined(TARGET_PPC64) */
2857068e 5826/* Full system - 32 bits mode */
0487d6a8
JM
5827#define OP_SPE_LD_TABLE(name) \
5828static GenOpFunc *gen_op_spe_l##name[] = { \
5829 &gen_op_spe_l##name##_user, \
5830 &gen_op_spe_l##name##_le_user, \
5831 &gen_op_spe_l##name##_kernel, \
5832 &gen_op_spe_l##name##_le_kernel, \
5833};
5834#define OP_SPE_ST_TABLE(name) \
5835static GenOpFunc *gen_op_spe_st##name[] = { \
5836 &gen_op_spe_st##name##_user, \
5837 &gen_op_spe_st##name##_le_user, \
5838 &gen_op_spe_st##name##_kernel, \
5839 &gen_op_spe_st##name##_le_kernel, \
5840};
5841#endif /* defined(TARGET_PPC64) */
5842#endif /* defined(CONFIG_USER_ONLY) */
5843
5844#define GEN_SPE_LD(name, sh) \
b068d6a7 5845static always_inline void gen_evl##name (DisasContext *ctx) \
0487d6a8
JM
5846{ \
5847 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 5848 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
5849 return; \
5850 } \
5851 gen_addr_spe_imm_index(ctx, sh); \
5852 op_spe_ldst(spe_l##name); \
5853 gen_op_store_T1_gpr64(rD(ctx->opcode)); \
5854}
5855
5856#define GEN_SPE_LDX(name) \
b068d6a7 5857static always_inline void gen_evl##name##x (DisasContext *ctx) \
0487d6a8
JM
5858{ \
5859 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 5860 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
5861 return; \
5862 } \
5863 gen_addr_reg_index(ctx); \
5864 op_spe_ldst(spe_l##name); \
5865 gen_op_store_T1_gpr64(rD(ctx->opcode)); \
5866}
5867
5868#define GEN_SPEOP_LD(name, sh) \
5869OP_SPE_LD_TABLE(name); \
5870GEN_SPE_LD(name, sh); \
5871GEN_SPE_LDX(name)
5872
5873#define GEN_SPE_ST(name, sh) \
b068d6a7 5874static always_inline void gen_evst##name (DisasContext *ctx) \
0487d6a8
JM
5875{ \
5876 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 5877 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
5878 return; \
5879 } \
5880 gen_addr_spe_imm_index(ctx, sh); \
5881 gen_op_load_gpr64_T1(rS(ctx->opcode)); \
5882 op_spe_ldst(spe_st##name); \
5883}
5884
5885#define GEN_SPE_STX(name) \
b068d6a7 5886static always_inline void gen_evst##name##x (DisasContext *ctx) \
0487d6a8
JM
5887{ \
5888 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 5889 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
5890 return; \
5891 } \
5892 gen_addr_reg_index(ctx); \
5893 gen_op_load_gpr64_T1(rS(ctx->opcode)); \
5894 op_spe_ldst(spe_st##name); \
5895}
5896
5897#define GEN_SPEOP_ST(name, sh) \
5898OP_SPE_ST_TABLE(name); \
5899GEN_SPE_ST(name, sh); \
5900GEN_SPE_STX(name)
5901
5902#define GEN_SPEOP_LDST(name, sh) \
5903GEN_SPEOP_LD(name, sh); \
5904GEN_SPEOP_ST(name, sh)
5905
5906/* SPE arithmetic and logic */
5907#define GEN_SPEOP_ARITH2(name) \
b068d6a7 5908static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
5909{ \
5910 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 5911 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
5912 return; \
5913 } \
5914 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
5915 gen_op_load_gpr64_T1(rB(ctx->opcode)); \
5916 gen_op_##name(); \
5917 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5918}
5919
5920#define GEN_SPEOP_ARITH1(name) \
b068d6a7 5921static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
5922{ \
5923 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 5924 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
5925 return; \
5926 } \
5927 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
5928 gen_op_##name(); \
5929 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5930}
5931
5932#define GEN_SPEOP_COMP(name) \
b068d6a7 5933static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
5934{ \
5935 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 5936 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
5937 return; \
5938 } \
5939 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
5940 gen_op_load_gpr64_T1(rB(ctx->opcode)); \
5941 gen_op_##name(); \
5942 gen_op_store_T0_crf(crfD(ctx->opcode)); \
5943}
5944
5945/* Logical */
5946GEN_SPEOP_ARITH2(evand);
5947GEN_SPEOP_ARITH2(evandc);
5948GEN_SPEOP_ARITH2(evxor);
5949GEN_SPEOP_ARITH2(evor);
5950GEN_SPEOP_ARITH2(evnor);
5951GEN_SPEOP_ARITH2(eveqv);
5952GEN_SPEOP_ARITH2(evorc);
5953GEN_SPEOP_ARITH2(evnand);
5954GEN_SPEOP_ARITH2(evsrwu);
5955GEN_SPEOP_ARITH2(evsrws);
5956GEN_SPEOP_ARITH2(evslw);
5957GEN_SPEOP_ARITH2(evrlw);
5958GEN_SPEOP_ARITH2(evmergehi);
5959GEN_SPEOP_ARITH2(evmergelo);
5960GEN_SPEOP_ARITH2(evmergehilo);
5961GEN_SPEOP_ARITH2(evmergelohi);
5962
5963/* Arithmetic */
5964GEN_SPEOP_ARITH2(evaddw);
5965GEN_SPEOP_ARITH2(evsubfw);
5966GEN_SPEOP_ARITH1(evabs);
5967GEN_SPEOP_ARITH1(evneg);
5968GEN_SPEOP_ARITH1(evextsb);
5969GEN_SPEOP_ARITH1(evextsh);
5970GEN_SPEOP_ARITH1(evrndw);
5971GEN_SPEOP_ARITH1(evcntlzw);
5972GEN_SPEOP_ARITH1(evcntlsw);
b068d6a7 5973static always_inline void gen_brinc (DisasContext *ctx)
0487d6a8
JM
5974{
5975 /* Note: brinc is usable even if SPE is disabled */
5976 gen_op_load_gpr64_T0(rA(ctx->opcode));
5977 gen_op_load_gpr64_T1(rB(ctx->opcode));
5978 gen_op_brinc();
5979 gen_op_store_T0_gpr64(rD(ctx->opcode));
5980}
5981
5982#define GEN_SPEOP_ARITH_IMM2(name) \
b068d6a7 5983static always_inline void gen_##name##i (DisasContext *ctx) \
0487d6a8
JM
5984{ \
5985 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 5986 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
5987 return; \
5988 } \
5989 gen_op_load_gpr64_T0(rB(ctx->opcode)); \
5990 gen_op_splatwi_T1_64(rA(ctx->opcode)); \
5991 gen_op_##name(); \
5992 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5993}
5994
5995#define GEN_SPEOP_LOGIC_IMM2(name) \
b068d6a7 5996static always_inline void gen_##name##i (DisasContext *ctx) \
0487d6a8
JM
5997{ \
5998 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 5999 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6000 return; \
6001 } \
6002 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
6003 gen_op_splatwi_T1_64(rB(ctx->opcode)); \
6004 gen_op_##name(); \
6005 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
6006}
6007
6008GEN_SPEOP_ARITH_IMM2(evaddw);
6009#define gen_evaddiw gen_evaddwi
6010GEN_SPEOP_ARITH_IMM2(evsubfw);
6011#define gen_evsubifw gen_evsubfwi
6012GEN_SPEOP_LOGIC_IMM2(evslw);
6013GEN_SPEOP_LOGIC_IMM2(evsrwu);
6014#define gen_evsrwis gen_evsrwsi
6015GEN_SPEOP_LOGIC_IMM2(evsrws);
6016#define gen_evsrwiu gen_evsrwui
6017GEN_SPEOP_LOGIC_IMM2(evrlw);
6018
b068d6a7 6019static always_inline void gen_evsplati (DisasContext *ctx)
0487d6a8
JM
6020{
6021 int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;
6022
6023 gen_op_splatwi_T0_64(imm);
6024 gen_op_store_T0_gpr64(rD(ctx->opcode));
6025}
6026
b068d6a7 6027static always_inline void gen_evsplatfi (DisasContext *ctx)
0487d6a8
JM
6028{
6029 uint32_t imm = rA(ctx->opcode) << 27;
6030
6031 gen_op_splatwi_T0_64(imm);
6032 gen_op_store_T0_gpr64(rD(ctx->opcode));
6033}
6034
6035/* Comparison */
6036GEN_SPEOP_COMP(evcmpgtu);
6037GEN_SPEOP_COMP(evcmpgts);
6038GEN_SPEOP_COMP(evcmpltu);
6039GEN_SPEOP_COMP(evcmplts);
6040GEN_SPEOP_COMP(evcmpeq);
6041
6042GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
6043GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
6044GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
6045GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
6046GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
6047GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
6048GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
6049GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
6050GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
6051GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
6052GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
6053GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
6054GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
6055GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
6056GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
6057GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
6058GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
6059GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
6060GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
6061GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
6062GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
6063GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
6064GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
6065GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
6066GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
6067
b068d6a7 6068static always_inline void gen_evsel (DisasContext *ctx)
0487d6a8
JM
6069{
6070 if (unlikely(!ctx->spe_enabled)) {
e1833e1f 6071 GEN_EXCP_NO_AP(ctx);
0487d6a8
JM
6072 return;
6073 }
6074 gen_op_load_crf_T0(ctx->opcode & 0x7);
6075 gen_op_load_gpr64_T0(rA(ctx->opcode));
6076 gen_op_load_gpr64_T1(rB(ctx->opcode));
6077 gen_op_evsel();
6078 gen_op_store_T0_gpr64(rD(ctx->opcode));
6079}
6080
6081GEN_HANDLER(evsel0, 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
6082{
6083 gen_evsel(ctx);
6084}
6085GEN_HANDLER(evsel1, 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
6086{
6087 gen_evsel(ctx);
6088}
6089GEN_HANDLER(evsel2, 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
6090{
6091 gen_evsel(ctx);
6092}
6093GEN_HANDLER(evsel3, 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
6094{
6095 gen_evsel(ctx);
6096}
6097
6098/* Load and stores */
6099#if defined(TARGET_PPC64)
6100/* In that case, we already have 64 bits load & stores
6101 * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
6102 */
6103#if defined(CONFIG_USER_ONLY)
6104#define gen_op_spe_ldd_raw gen_op_ld_raw
6105#define gen_op_spe_ldd_64_raw gen_op_ld_64_raw
6106#define gen_op_spe_ldd_le_raw gen_op_ld_le_raw
6107#define gen_op_spe_ldd_le_64_raw gen_op_ld_le_64_raw
6108#define gen_op_spe_stdd_raw gen_op_ld_raw
6109#define gen_op_spe_stdd_64_raw gen_op_std_64_raw
6110#define gen_op_spe_stdd_le_raw gen_op_std_le_raw
6111#define gen_op_spe_stdd_le_64_raw gen_op_std_le_64_raw
6112#else /* defined(CONFIG_USER_ONLY) */
6113#define gen_op_spe_ldd_kernel gen_op_ld_kernel
6114#define gen_op_spe_ldd_64_kernel gen_op_ld_64_kernel
6115#define gen_op_spe_ldd_le_kernel gen_op_ld_kernel
6116#define gen_op_spe_ldd_le_64_kernel gen_op_ld_64_kernel
6117#define gen_op_spe_ldd_user gen_op_ld_user
6118#define gen_op_spe_ldd_64_user gen_op_ld_64_user
6119#define gen_op_spe_ldd_le_user gen_op_ld_le_user
6120#define gen_op_spe_ldd_le_64_user gen_op_ld_le_64_user
6121#define gen_op_spe_stdd_kernel gen_op_std_kernel
6122#define gen_op_spe_stdd_64_kernel gen_op_std_64_kernel
6123#define gen_op_spe_stdd_le_kernel gen_op_std_kernel
6124#define gen_op_spe_stdd_le_64_kernel gen_op_std_64_kernel
6125#define gen_op_spe_stdd_user gen_op_std_user
6126#define gen_op_spe_stdd_64_user gen_op_std_64_user
6127#define gen_op_spe_stdd_le_user gen_op_std_le_user
6128#define gen_op_spe_stdd_le_64_user gen_op_std_le_64_user
6129#endif /* defined(CONFIG_USER_ONLY) */
6130#endif /* defined(TARGET_PPC64) */
6131GEN_SPEOP_LDST(dd, 3);
6132GEN_SPEOP_LDST(dw, 3);
6133GEN_SPEOP_LDST(dh, 3);
6134GEN_SPEOP_LDST(whe, 2);
6135GEN_SPEOP_LD(whou, 2);
6136GEN_SPEOP_LD(whos, 2);
6137GEN_SPEOP_ST(who, 2);
6138
6139#if defined(TARGET_PPC64)
6140/* In that case, spe_stwwo is equivalent to stw */
6141#if defined(CONFIG_USER_ONLY)
6142#define gen_op_spe_stwwo_raw gen_op_stw_raw
6143#define gen_op_spe_stwwo_le_raw gen_op_stw_le_raw
6144#define gen_op_spe_stwwo_64_raw gen_op_stw_64_raw
6145#define gen_op_spe_stwwo_le_64_raw gen_op_stw_le_64_raw
6146#else
6147#define gen_op_spe_stwwo_user gen_op_stw_user
6148#define gen_op_spe_stwwo_le_user gen_op_stw_le_user
6149#define gen_op_spe_stwwo_64_user gen_op_stw_64_user
6150#define gen_op_spe_stwwo_le_64_user gen_op_stw_le_64_user
6151#define gen_op_spe_stwwo_kernel gen_op_stw_kernel
6152#define gen_op_spe_stwwo_le_kernel gen_op_stw_le_kernel
6153#define gen_op_spe_stwwo_64_kernel gen_op_stw_64_kernel
6154#define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
6155#endif
6156#endif
6157#define _GEN_OP_SPE_STWWE(suffix) \
b068d6a7 6158static always_inline void gen_op_spe_stwwe_##suffix (void) \
0487d6a8
JM
6159{ \
6160 gen_op_srli32_T1_64(); \
6161 gen_op_spe_stwwo_##suffix(); \
6162}
6163#define _GEN_OP_SPE_STWWE_LE(suffix) \
b068d6a7 6164static always_inline void gen_op_spe_stwwe_le_##suffix (void) \
0487d6a8
JM
6165{ \
6166 gen_op_srli32_T1_64(); \
6167 gen_op_spe_stwwo_le_##suffix(); \
6168}
6169#if defined(TARGET_PPC64)
6170#define GEN_OP_SPE_STWWE(suffix) \
6171_GEN_OP_SPE_STWWE(suffix); \
6172_GEN_OP_SPE_STWWE_LE(suffix); \
b068d6a7 6173static always_inline void gen_op_spe_stwwe_64_##suffix (void) \
0487d6a8
JM
6174{ \
6175 gen_op_srli32_T1_64(); \
6176 gen_op_spe_stwwo_64_##suffix(); \
6177} \
b068d6a7 6178static always_inline void gen_op_spe_stwwe_le_64_##suffix (void) \
0487d6a8
JM
6179{ \
6180 gen_op_srli32_T1_64(); \
6181 gen_op_spe_stwwo_le_64_##suffix(); \
6182}
6183#else
6184#define GEN_OP_SPE_STWWE(suffix) \
6185_GEN_OP_SPE_STWWE(suffix); \
6186_GEN_OP_SPE_STWWE_LE(suffix)
6187#endif
6188#if defined(CONFIG_USER_ONLY)
6189GEN_OP_SPE_STWWE(raw);
6190#else /* defined(CONFIG_USER_ONLY) */
6191GEN_OP_SPE_STWWE(kernel);
6192GEN_OP_SPE_STWWE(user);
6193#endif /* defined(CONFIG_USER_ONLY) */
6194GEN_SPEOP_ST(wwe, 2);
6195GEN_SPEOP_ST(wwo, 2);
6196
6197#define GEN_SPE_LDSPLAT(name, op, suffix) \
b068d6a7 6198static always_inline void gen_op_spe_l##name##_##suffix (void) \
0487d6a8
JM
6199{ \
6200 gen_op_##op##_##suffix(); \
6201 gen_op_splatw_T1_64(); \
6202}
6203
6204#define GEN_OP_SPE_LHE(suffix) \
b068d6a7 6205static always_inline void gen_op_spe_lhe_##suffix (void) \
0487d6a8
JM
6206{ \
6207 gen_op_spe_lh_##suffix(); \
6208 gen_op_sli16_T1_64(); \
6209}
6210
6211#define GEN_OP_SPE_LHX(suffix) \
b068d6a7 6212static always_inline void gen_op_spe_lhx_##suffix (void) \
0487d6a8
JM
6213{ \
6214 gen_op_spe_lh_##suffix(); \
6215 gen_op_extsh_T1_64(); \
6216}
6217
6218#if defined(CONFIG_USER_ONLY)
6219GEN_OP_SPE_LHE(raw);
6220GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
6221GEN_OP_SPE_LHE(le_raw);
6222GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
6223GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
6224GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
6225GEN_OP_SPE_LHX(raw);
6226GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
6227GEN_OP_SPE_LHX(le_raw);
6228GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
6229#if defined(TARGET_PPC64)
6230GEN_OP_SPE_LHE(64_raw);
6231GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
6232GEN_OP_SPE_LHE(le_64_raw);
6233GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
6234GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
6235GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
6236GEN_OP_SPE_LHX(64_raw);
6237GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
6238GEN_OP_SPE_LHX(le_64_raw);
6239GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
6240#endif
6241#else
6242GEN_OP_SPE_LHE(kernel);
6243GEN_OP_SPE_LHE(user);
6244GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
6245GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
6246GEN_OP_SPE_LHE(le_kernel);
6247GEN_OP_SPE_LHE(le_user);
6248GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
6249GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
6250GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
6251GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
6252GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
6253GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
6254GEN_OP_SPE_LHX(kernel);
6255GEN_OP_SPE_LHX(user);
6256GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
6257GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
6258GEN_OP_SPE_LHX(le_kernel);
6259GEN_OP_SPE_LHX(le_user);
6260GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
6261GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
6262#if defined(TARGET_PPC64)
6263GEN_OP_SPE_LHE(64_kernel);
6264GEN_OP_SPE_LHE(64_user);
6265GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
6266GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
6267GEN_OP_SPE_LHE(le_64_kernel);
6268GEN_OP_SPE_LHE(le_64_user);
6269GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
6270GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
6271GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
6272GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
6273GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
6274GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
6275GEN_OP_SPE_LHX(64_kernel);
6276GEN_OP_SPE_LHX(64_user);
6277GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
6278GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
6279GEN_OP_SPE_LHX(le_64_kernel);
6280GEN_OP_SPE_LHX(le_64_user);
6281GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
6282GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
6283#endif
6284#endif
6285GEN_SPEOP_LD(hhesplat, 1);
6286GEN_SPEOP_LD(hhousplat, 1);
6287GEN_SPEOP_LD(hhossplat, 1);
6288GEN_SPEOP_LD(wwsplat, 2);
6289GEN_SPEOP_LD(whsplat, 2);
6290
6291GEN_SPE(evlddx, evldd, 0x00, 0x0C, 0x00000000, PPC_SPE); //
6292GEN_SPE(evldwx, evldw, 0x01, 0x0C, 0x00000000, PPC_SPE); //
6293GEN_SPE(evldhx, evldh, 0x02, 0x0C, 0x00000000, PPC_SPE); //
6294GEN_SPE(evlhhesplatx, evlhhesplat, 0x04, 0x0C, 0x00000000, PPC_SPE); //
6295GEN_SPE(evlhhousplatx, evlhhousplat, 0x06, 0x0C, 0x00000000, PPC_SPE); //
6296GEN_SPE(evlhhossplatx, evlhhossplat, 0x07, 0x0C, 0x00000000, PPC_SPE); //
6297GEN_SPE(evlwhex, evlwhe, 0x08, 0x0C, 0x00000000, PPC_SPE); //
6298GEN_SPE(evlwhoux, evlwhou, 0x0A, 0x0C, 0x00000000, PPC_SPE); //
6299GEN_SPE(evlwhosx, evlwhos, 0x0B, 0x0C, 0x00000000, PPC_SPE); //
6300GEN_SPE(evlwwsplatx, evlwwsplat, 0x0C, 0x0C, 0x00000000, PPC_SPE); //
6301GEN_SPE(evlwhsplatx, evlwhsplat, 0x0E, 0x0C, 0x00000000, PPC_SPE); //
6302GEN_SPE(evstddx, evstdd, 0x10, 0x0C, 0x00000000, PPC_SPE); //
6303GEN_SPE(evstdwx, evstdw, 0x11, 0x0C, 0x00000000, PPC_SPE); //
6304GEN_SPE(evstdhx, evstdh, 0x12, 0x0C, 0x00000000, PPC_SPE); //
6305GEN_SPE(evstwhex, evstwhe, 0x18, 0x0C, 0x00000000, PPC_SPE); //
6306GEN_SPE(evstwhox, evstwho, 0x1A, 0x0C, 0x00000000, PPC_SPE); //
6307GEN_SPE(evstwwex, evstwwe, 0x1C, 0x0C, 0x00000000, PPC_SPE); //
6308GEN_SPE(evstwwox, evstwwo, 0x1E, 0x0C, 0x00000000, PPC_SPE); //
6309
6310/* Multiply and add - TODO */
6311#if 0
6312GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
6313GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
6314GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
6315GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
6316GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
6317GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
6318GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
6319GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
6320GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
6321GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
6322GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
6323GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
6324
6325GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
6326GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
6327GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
6328GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
6329GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
6330GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
6331GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
6332GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
6333GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
6334GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
6335GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
6336GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
6337GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
6338GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
6339
6340GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
6341GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
6342GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
6343GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
6344GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
6345GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
6346
6347GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
6348GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
6349GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
6350GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
6351GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
6352GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
6353GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
6354GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
6355GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
6356GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
6357GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
6358GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
6359
6360GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
6361GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
6362GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
6363GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
6364GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
6365
6366GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
6367GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
6368GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
6369GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
6370GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
6371GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
6372GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
6373GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
6374GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
6375GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
6376GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
6377GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
6378
6379GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
6380GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
6381GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
6382GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
6383GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
6384#endif
6385
6386/*** SPE floating-point extension ***/
6387#define GEN_SPEFPUOP_CONV(name) \
b068d6a7 6388static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6389{ \
6390 gen_op_load_gpr64_T0(rB(ctx->opcode)); \
6391 gen_op_##name(); \
6392 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
6393}
6394
6395/* Single precision floating-point vectors operations */
6396/* Arithmetic */
6397GEN_SPEOP_ARITH2(evfsadd);
6398GEN_SPEOP_ARITH2(evfssub);
6399GEN_SPEOP_ARITH2(evfsmul);
6400GEN_SPEOP_ARITH2(evfsdiv);
6401GEN_SPEOP_ARITH1(evfsabs);
6402GEN_SPEOP_ARITH1(evfsnabs);
6403GEN_SPEOP_ARITH1(evfsneg);
6404/* Conversion */
6405GEN_SPEFPUOP_CONV(evfscfui);
6406GEN_SPEFPUOP_CONV(evfscfsi);
6407GEN_SPEFPUOP_CONV(evfscfuf);
6408GEN_SPEFPUOP_CONV(evfscfsf);
6409GEN_SPEFPUOP_CONV(evfsctui);
6410GEN_SPEFPUOP_CONV(evfsctsi);
6411GEN_SPEFPUOP_CONV(evfsctuf);
6412GEN_SPEFPUOP_CONV(evfsctsf);
6413GEN_SPEFPUOP_CONV(evfsctuiz);
6414GEN_SPEFPUOP_CONV(evfsctsiz);
6415/* Comparison */
6416GEN_SPEOP_COMP(evfscmpgt);
6417GEN_SPEOP_COMP(evfscmplt);
6418GEN_SPEOP_COMP(evfscmpeq);
6419GEN_SPEOP_COMP(evfststgt);
6420GEN_SPEOP_COMP(evfststlt);
6421GEN_SPEOP_COMP(evfststeq);
6422
6423/* Opcodes definitions */
6424GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
6425GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
6426GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
6427GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
6428GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
6429GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
6430GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
6431GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
6432GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
6433GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
6434GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
6435GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
6436GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
6437GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
6438
6439/* Single precision floating-point operations */
6440/* Arithmetic */
6441GEN_SPEOP_ARITH2(efsadd);
6442GEN_SPEOP_ARITH2(efssub);
6443GEN_SPEOP_ARITH2(efsmul);
6444GEN_SPEOP_ARITH2(efsdiv);
6445GEN_SPEOP_ARITH1(efsabs);
6446GEN_SPEOP_ARITH1(efsnabs);
6447GEN_SPEOP_ARITH1(efsneg);
6448/* Conversion */
6449GEN_SPEFPUOP_CONV(efscfui);
6450GEN_SPEFPUOP_CONV(efscfsi);
6451GEN_SPEFPUOP_CONV(efscfuf);
6452GEN_SPEFPUOP_CONV(efscfsf);
6453GEN_SPEFPUOP_CONV(efsctui);
6454GEN_SPEFPUOP_CONV(efsctsi);
6455GEN_SPEFPUOP_CONV(efsctuf);
6456GEN_SPEFPUOP_CONV(efsctsf);
6457GEN_SPEFPUOP_CONV(efsctuiz);
6458GEN_SPEFPUOP_CONV(efsctsiz);
6459GEN_SPEFPUOP_CONV(efscfd);
6460/* Comparison */
6461GEN_SPEOP_COMP(efscmpgt);
6462GEN_SPEOP_COMP(efscmplt);
6463GEN_SPEOP_COMP(efscmpeq);
6464GEN_SPEOP_COMP(efststgt);
6465GEN_SPEOP_COMP(efststlt);
6466GEN_SPEOP_COMP(efststeq);
6467
6468/* Opcodes definitions */
6469GEN_SPE(efsadd, efssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
6470GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
6471GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
6472GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
6473GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
6474GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
6475GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
6476GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
6477GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
6478GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
6479GEN_SPE(efsctuiz, efsctsiz, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
6480GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
6481GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
6482
6483/* Double precision floating-point operations */
6484/* Arithmetic */
6485GEN_SPEOP_ARITH2(efdadd);
6486GEN_SPEOP_ARITH2(efdsub);
6487GEN_SPEOP_ARITH2(efdmul);
6488GEN_SPEOP_ARITH2(efddiv);
6489GEN_SPEOP_ARITH1(efdabs);
6490GEN_SPEOP_ARITH1(efdnabs);
6491GEN_SPEOP_ARITH1(efdneg);
6492/* Conversion */
6493
6494GEN_SPEFPUOP_CONV(efdcfui);
6495GEN_SPEFPUOP_CONV(efdcfsi);
6496GEN_SPEFPUOP_CONV(efdcfuf);
6497GEN_SPEFPUOP_CONV(efdcfsf);
6498GEN_SPEFPUOP_CONV(efdctui);
6499GEN_SPEFPUOP_CONV(efdctsi);
6500GEN_SPEFPUOP_CONV(efdctuf);
6501GEN_SPEFPUOP_CONV(efdctsf);
6502GEN_SPEFPUOP_CONV(efdctuiz);
6503GEN_SPEFPUOP_CONV(efdctsiz);
6504GEN_SPEFPUOP_CONV(efdcfs);
6505GEN_SPEFPUOP_CONV(efdcfuid);
6506GEN_SPEFPUOP_CONV(efdcfsid);
6507GEN_SPEFPUOP_CONV(efdctuidz);
6508GEN_SPEFPUOP_CONV(efdctsidz);
6509/* Comparison */
6510GEN_SPEOP_COMP(efdcmpgt);
6511GEN_SPEOP_COMP(efdcmplt);
6512GEN_SPEOP_COMP(efdcmpeq);
6513GEN_SPEOP_COMP(efdtstgt);
6514GEN_SPEOP_COMP(efdtstlt);
6515GEN_SPEOP_COMP(efdtsteq);
6516
6517/* Opcodes definitions */
6518GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
6519GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
6520GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
6521GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
6522GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
6523GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
6524GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
6525GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
6526GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
6527GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
6528GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
6529GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
6530GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
6531GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
6532GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
6533GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
6534#endif
6535
79aceca5
FB
6536/* End opcode list */
6537GEN_OPCODE_MARK(end);
6538
3fc6c082 6539#include "translate_init.c"
79aceca5 6540
9a64fbe4 6541/*****************************************************************************/
3fc6c082 6542/* Misc PowerPC helpers */
b068d6a7 6543static always_inline uint32_t load_xer (CPUState *env)
76a66253
JM
6544{
6545 return (xer_so << XER_SO) |
6546 (xer_ov << XER_OV) |
6547 (xer_ca << XER_CA) |
6548 (xer_bc << XER_BC) |
6549 (xer_cmp << XER_CMP);
6550}
6551
36081602
JM
6552void cpu_dump_state (CPUState *env, FILE *f,
6553 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6554 int flags)
79aceca5 6555{
3fc6c082
FB
6556#if defined(TARGET_PPC64) || 1
6557#define FILL ""
3fc6c082
FB
6558#define RGPL 4
6559#define RFPL 4
6560#else
6561#define FILL " "
3fc6c082
FB
6562#define RGPL 8
6563#define RFPL 4
6564#endif
6565
79aceca5
FB
6566 int i;
6567
1b9eb036 6568 cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX "\n",
3fc6c082 6569 env->nip, env->lr, env->ctr);
d9bce9d9
JM
6570 cpu_fprintf(f, "MSR " REGX FILL " XER %08x "
6571#if !defined(NO_TIMER_DUMP)
6572 "TB %08x %08x "
76a66253
JM
6573#if !defined(CONFIG_USER_ONLY)
6574 "DECR %08x"
d9bce9d9 6575#endif
76a66253
JM
6576#endif
6577 "\n",
d9bce9d9
JM
6578 do_load_msr(env), load_xer(env)
6579#if !defined(NO_TIMER_DUMP)
6580 , cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
76a66253
JM
6581#if !defined(CONFIG_USER_ONLY)
6582 , cpu_ppc_load_decr(env)
d9bce9d9 6583#endif
76a66253
JM
6584#endif
6585 );
6586 for (i = 0; i < 32; i++) {
3fc6c082
FB
6587 if ((i & (RGPL - 1)) == 0)
6588 cpu_fprintf(f, "GPR%02d", i);
a750fc0b 6589 cpu_fprintf(f, " " REGX, (target_ulong)env->gpr[i]);
3fc6c082 6590 if ((i & (RGPL - 1)) == (RGPL - 1))
7fe48483 6591 cpu_fprintf(f, "\n");
76a66253 6592 }
3fc6c082 6593 cpu_fprintf(f, "CR ");
76a66253 6594 for (i = 0; i < 8; i++)
7fe48483
FB
6595 cpu_fprintf(f, "%01x", env->crf[i]);
6596 cpu_fprintf(f, " [");
76a66253
JM
6597 for (i = 0; i < 8; i++) {
6598 char a = '-';
6599 if (env->crf[i] & 0x08)
6600 a = 'L';
6601 else if (env->crf[i] & 0x04)
6602 a = 'G';
6603 else if (env->crf[i] & 0x02)
6604 a = 'E';
7fe48483 6605 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
76a66253 6606 }
3fc6c082
FB
6607 cpu_fprintf(f, " ] " FILL "RES " REGX "\n", env->reserve);
6608 for (i = 0; i < 32; i++) {
6609 if ((i & (RFPL - 1)) == 0)
6610 cpu_fprintf(f, "FPR%02d", i);
26a76461 6611 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
3fc6c082 6612 if ((i & (RFPL - 1)) == (RFPL - 1))
7fe48483 6613 cpu_fprintf(f, "\n");
79aceca5 6614 }
f2e63a42 6615#if !defined(CONFIG_USER_ONLY)
3fc6c082
FB
6616 cpu_fprintf(f, "SRR0 " REGX " SRR1 " REGX " " FILL FILL FILL
6617 "SDR1 " REGX "\n",
6618 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
f2e63a42 6619#endif
79aceca5 6620
3fc6c082
FB
6621#undef RGPL
6622#undef RFPL
6623#undef FILL
79aceca5
FB
6624}
6625
76a66253
JM
6626void cpu_dump_statistics (CPUState *env, FILE*f,
6627 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6628 int flags)
6629{
6630#if defined(DO_PPC_STATISTICS)
6631 opc_handler_t **t1, **t2, **t3, *handler;
6632 int op1, op2, op3;
6633
6634 t1 = env->opcodes;
6635 for (op1 = 0; op1 < 64; op1++) {
6636 handler = t1[op1];
6637 if (is_indirect_opcode(handler)) {
6638 t2 = ind_table(handler);
6639 for (op2 = 0; op2 < 32; op2++) {
6640 handler = t2[op2];
6641 if (is_indirect_opcode(handler)) {
6642 t3 = ind_table(handler);
6643 for (op3 = 0; op3 < 32; op3++) {
6644 handler = t3[op3];
6645 if (handler->count == 0)
6646 continue;
6647 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
6648 "%016llx %lld\n",
6649 op1, op2, op3, op1, (op3 << 5) | op2,
6650 handler->oname,
6651 handler->count, handler->count);
6652 }
6653 } else {
6654 if (handler->count == 0)
6655 continue;
6656 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
6657 "%016llx %lld\n",
6658 op1, op2, op1, op2, handler->oname,
6659 handler->count, handler->count);
6660 }
6661 }
6662 } else {
6663 if (handler->count == 0)
6664 continue;
6665 cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
6666 op1, op1, handler->oname,
6667 handler->count, handler->count);
6668 }
6669 }
6670#endif
6671}
6672
9a64fbe4 6673/*****************************************************************************/
b068d6a7
JM
6674static always_inline int gen_intermediate_code_internal (CPUState *env,
6675 TranslationBlock *tb,
6676 int search_pc)
79aceca5 6677{
9fddaa0c 6678 DisasContext ctx, *ctxp = &ctx;
79aceca5 6679 opc_handler_t **table, *handler;
0fa85d43 6680 target_ulong pc_start;
79aceca5 6681 uint16_t *gen_opc_end;
2857068e 6682 int supervisor;
d26bfc9a 6683 int single_step, branch_step;
79aceca5 6684 int j, lj = -1;
79aceca5
FB
6685
6686 pc_start = tb->pc;
6687 gen_opc_ptr = gen_opc_buf;
6688 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6689 gen_opparam_ptr = gen_opparam_buf;
c53be334 6690 nb_gen_labels = 0;
046d6672 6691 ctx.nip = pc_start;
79aceca5 6692 ctx.tb = tb;
e1833e1f 6693 ctx.exception = POWERPC_EXCP_NONE;
3fc6c082 6694 ctx.spr_cb = env->spr_cb;
9a64fbe4 6695#if defined(CONFIG_USER_ONLY)
2857068e 6696 supervisor = 0;
9a64fbe4 6697#else
be147d08
JM
6698#if defined(TARGET_PPC64H)
6699 if (msr_pr == 0 && msr_hv == 1)
2857068e 6700 supervisor = 2;
be147d08
JM
6701 else
6702#endif
2857068e
JM
6703 supervisor = 1 - msr_pr;
6704 ctx.supervisor = supervisor;
d9bce9d9
JM
6705#endif
6706#if defined(TARGET_PPC64)
6707 ctx.sf_mode = msr_sf;
2857068e
JM
6708 ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | msr_le;
6709#else
6710 ctx.mem_idx = (supervisor << 1) | msr_le;
9a64fbe4 6711#endif
d63001d1 6712 ctx.dcache_line_size = env->dcache_line_size;
3cc62370 6713 ctx.fpu_enabled = msr_fp;
35cdaad6 6714#if defined(TARGET_PPCEMB)
a9d9eb8f 6715 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
d26bfc9a
JM
6716 ctx.spe_enabled = msr_spe;
6717 else
6718 ctx.spe_enabled = 0;
0487d6a8 6719#endif
a9d9eb8f
JM
6720 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
6721 ctx.altivec_enabled = msr_vr;
6722 else
6723 ctx.altivec_enabled = 0;
d26bfc9a
JM
6724 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
6725 single_step = 1;
6726 else
6727 single_step = 0;
6728 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
6729 branch_step = 1;
6730 else
6731 branch_step = 0;
b33c17e1 6732 ctx.singlestep_enabled = env->singlestep_enabled || single_step == 1;
3fc6c082 6733#if defined (DO_SINGLE_STEP) && 0
9a64fbe4
FB
6734 /* Single step trace mode */
6735 msr_se = 1;
6736#endif
6737 /* Set env in case of segfault during code fetch */
e1833e1f 6738 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
76a66253
JM
6739 if (unlikely(env->nb_breakpoints > 0)) {
6740 for (j = 0; j < env->nb_breakpoints; j++) {
ea4e754f 6741 if (env->breakpoints[j] == ctx.nip) {
5fafdf24 6742 gen_update_nip(&ctx, ctx.nip);
ea4e754f
FB
6743 gen_op_debug();
6744 break;
6745 }
6746 }
6747 }
76a66253 6748 if (unlikely(search_pc)) {
79aceca5
FB
6749 j = gen_opc_ptr - gen_opc_buf;
6750 if (lj < j) {
6751 lj++;
6752 while (lj < j)
6753 gen_opc_instr_start[lj++] = 0;
046d6672 6754 gen_opc_pc[lj] = ctx.nip;
79aceca5
FB
6755 gen_opc_instr_start[lj] = 1;
6756 }
6757 }
9fddaa0c
FB
6758#if defined PPC_DEBUG_DISAS
6759 if (loglevel & CPU_LOG_TB_IN_ASM) {
79aceca5 6760 fprintf(logfile, "----------------\n");
1b9eb036 6761 fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
9a64fbe4
FB
6762 ctx.nip, 1 - msr_pr, msr_ir);
6763 }
6764#endif
0fa85d43 6765 ctx.opcode = ldl_code(ctx.nip);
111bfab3
FB
6766 if (msr_le) {
6767 ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) |
6768 ((ctx.opcode & 0x00FF0000) >> 8) |
6769 ((ctx.opcode & 0x0000FF00) << 8) |
6770 ((ctx.opcode & 0x000000FF) << 24);
6771 }
9fddaa0c
FB
6772#if defined PPC_DEBUG_DISAS
6773 if (loglevel & CPU_LOG_TB_IN_ASM) {
111bfab3 6774 fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
9a64fbe4 6775 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
111bfab3 6776 opc3(ctx.opcode), msr_le ? "little" : "big");
79aceca5
FB
6777 }
6778#endif
046d6672 6779 ctx.nip += 4;
3fc6c082 6780 table = env->opcodes;
79aceca5
FB
6781 handler = table[opc1(ctx.opcode)];
6782 if (is_indirect_opcode(handler)) {
6783 table = ind_table(handler);
6784 handler = table[opc2(ctx.opcode)];
6785 if (is_indirect_opcode(handler)) {
6786 table = ind_table(handler);
6787 handler = table[opc3(ctx.opcode)];
6788 }
6789 }
6790 /* Is opcode *REALLY* valid ? */
76a66253 6791 if (unlikely(handler->handler == &gen_invalid)) {
4a057712 6792 if (loglevel != 0) {
76a66253 6793 fprintf(logfile, "invalid/unsupported opcode: "
1b9eb036 6794 "%02x - %02x - %02x (%08x) 0x" ADDRX " %d\n",
76a66253 6795 opc1(ctx.opcode), opc2(ctx.opcode),
4b3686fa
FB
6796 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
6797 } else {
6798 printf("invalid/unsupported opcode: "
1b9eb036 6799 "%02x - %02x - %02x (%08x) 0x" ADDRX " %d\n",
4b3686fa
FB
6800 opc1(ctx.opcode), opc2(ctx.opcode),
6801 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
6802 }
76a66253
JM
6803 } else {
6804 if (unlikely((ctx.opcode & handler->inval) != 0)) {
4a057712 6805 if (loglevel != 0) {
79aceca5 6806 fprintf(logfile, "invalid bits: %08x for opcode: "
e1833e1f 6807 "%02x - %02x - %02x (%08x) 0x" ADDRX "\n",
79aceca5
FB
6808 ctx.opcode & handler->inval, opc1(ctx.opcode),
6809 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 6810 ctx.opcode, ctx.nip - 4);
9a64fbe4
FB
6811 } else {
6812 printf("invalid bits: %08x for opcode: "
e1833e1f 6813 "%02x - %02x - %02x (%08x) 0x" ADDRX "\n",
76a66253
JM
6814 ctx.opcode & handler->inval, opc1(ctx.opcode),
6815 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 6816 ctx.opcode, ctx.nip - 4);
76a66253 6817 }
e1833e1f 6818 GEN_EXCP_INVAL(ctxp);
4b3686fa 6819 break;
79aceca5 6820 }
79aceca5 6821 }
4b3686fa 6822 (*(handler->handler))(&ctx);
76a66253
JM
6823#if defined(DO_PPC_STATISTICS)
6824 handler->count++;
6825#endif
9a64fbe4 6826 /* Check trace mode exceptions */
d26bfc9a
JM
6827 if (unlikely(branch_step != 0 &&
6828 ctx.exception == POWERPC_EXCP_BRANCH)) {
6829 GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
6830 } else if (unlikely(single_step != 0 &&
6831 (ctx.nip <= 0x100 || ctx.nip > 0xF00 ||
6832 (ctx.nip & 0xFC) != 0x04) &&
e1833e1f 6833#if defined(CONFIG_USER_ONLY)
d26bfc9a 6834 ctx.exception != POWERPC_EXCP_SYSCALL_USER &&
e1833e1f 6835#else
d26bfc9a 6836 ctx.exception != POWERPC_EXCP_SYSCALL &&
e1833e1f 6837#endif
d26bfc9a 6838 ctx.exception != POWERPC_EXCP_TRAP)) {
e1833e1f 6839 GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
d26bfc9a
JM
6840 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
6841 (env->singlestep_enabled))) {
6842 /* if we reach a page boundary or are single stepping, stop
6843 * generation
6844 */
8dd4983c 6845 break;
76a66253 6846 }
3fc6c082
FB
6847#if defined (DO_SINGLE_STEP)
6848 break;
6849#endif
6850 }
e1833e1f 6851 if (ctx.exception == POWERPC_EXCP_NONE) {
c1942362 6852 gen_goto_tb(&ctx, 0, ctx.nip);
e1833e1f 6853 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
76a66253
JM
6854 gen_op_reset_T0();
6855 /* Generate the return instruction */
6856 gen_op_exit_tb();
9a64fbe4 6857 }
79aceca5 6858 *gen_opc_ptr = INDEX_op_end;
76a66253 6859 if (unlikely(search_pc)) {
9a64fbe4
FB
6860 j = gen_opc_ptr - gen_opc_buf;
6861 lj++;
6862 while (lj <= j)
6863 gen_opc_instr_start[lj++] = 0;
9a64fbe4 6864 } else {
046d6672 6865 tb->size = ctx.nip - pc_start;
9a64fbe4 6866 }
d9bce9d9 6867#if defined(DEBUG_DISAS)
9fddaa0c 6868 if (loglevel & CPU_LOG_TB_CPU) {
9a64fbe4 6869 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
7fe48483 6870 cpu_dump_state(env, logfile, fprintf, 0);
9fddaa0c
FB
6871 }
6872 if (loglevel & CPU_LOG_TB_IN_ASM) {
76a66253 6873 int flags;
237c0af0
JM
6874 flags = env->bfd_mach;
6875 flags |= msr_le << 16;
0fa85d43 6876 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
76a66253 6877 target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
79aceca5 6878 fprintf(logfile, "\n");
9fddaa0c
FB
6879 }
6880 if (loglevel & CPU_LOG_TB_OP) {
79aceca5
FB
6881 fprintf(logfile, "OP:\n");
6882 dump_ops(gen_opc_buf, gen_opparam_buf);
6883 fprintf(logfile, "\n");
6884 }
6885#endif
79aceca5
FB
6886 return 0;
6887}
6888
9a64fbe4 6889int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
79aceca5
FB
6890{
6891 return gen_intermediate_code_internal(env, tb, 0);
6892}
6893
9a64fbe4 6894int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
79aceca5
FB
6895{
6896 return gen_intermediate_code_internal(env, tb, 1);
6897}