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