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