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