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